home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / comm / tcp / samba_2.0.7.lha / source / amiga_rcs / amiga.c < prev    next >
C/C++ Source or Header  |  2000-12-25  |  197KB  |  10,125 lines

  1. head    1.16;
  2. access;
  3. symbols
  4.     V1_19:1.16
  5.     V1_18:1.15
  6.     V1_15:1.14
  7.     V1_12:1.13
  8.     V1_11:1.12
  9.     V1_10:1.11
  10.     V1_9:1.10
  11.     V1_8:1.9
  12.     V1_7:1.8
  13.     V1_6:1.7
  14.     V1_5:1.6
  15.     V1_4:1.4
  16.     V1_3:1.3
  17.     V1_2:1.2
  18.     V1_1:1.1;
  19. locks
  20.     olsen:1.16; strict;
  21. comment    @ * @;
  22.  
  23.  
  24. 1.16
  25. date    2000.12.25.11.41.23;    author olsen;    state Exp;
  26. branches;
  27. next    1.15;
  28.  
  29. 1.15
  30. date    2000.12.17.10.10.14;    author olsen;    state Exp;
  31. branches;
  32. next    1.14;
  33.  
  34. 1.14
  35. date    2000.05.24.19.50.17;    author olsen;    state Exp;
  36. branches;
  37. next    1.13;
  38.  
  39. 1.13
  40. date    99.12.25.11.31.10;    author olsen;    state Exp;
  41. branches;
  42. next    1.12;
  43.  
  44. 1.12
  45. date    99.12.01.09.47.07;    author olsen;    state Exp;
  46. branches;
  47. next    1.11;
  48.  
  49. 1.11
  50. date    99.11.06.16.03.15;    author olsen;    state Exp;
  51. branches;
  52. next    1.10;
  53.  
  54. 1.10
  55. date    99.10.16.09.15.58;    author olsen;    state Exp;
  56. branches;
  57. next    1.9;
  58.  
  59. 1.9
  60. date    99.08.09.15.28.43;    author olsen;    state Exp;
  61. branches;
  62. next    1.8;
  63.  
  64. 1.8
  65. date    99.05.21.09.38.15;    author olsen;    state Exp;
  66. branches;
  67. next    1.7;
  68.  
  69. 1.7
  70. date    99.05.02.10.45.08;    author olsen;    state Exp;
  71. branches;
  72. next    1.6;
  73.  
  74. 1.6
  75. date    99.02.28.09.16.53;    author olsen;    state Exp;
  76. branches;
  77. next    1.5;
  78.  
  79. 1.5
  80. date    99.02.22.15.31.18;    author olsen;    state Exp;
  81. branches;
  82. next    1.4;
  83.  
  84. 1.4
  85. date    99.02.21.10.58.42;    author olsen;    state Exp;
  86. branches;
  87. next    1.3;
  88.  
  89. 1.3
  90. date    99.02.20.17.52.48;    author olsen;    state Exp;
  91. branches;
  92. next    1.2;
  93.  
  94. 1.2
  95. date    99.02.20.16.52.05;    author olsen;    state Exp;
  96. branches;
  97. next    1.1;
  98.  
  99. 1.1
  100. date    99.02.13.15.32.16;    author olsen;    state Exp;
  101. branches;
  102. next    ;
  103.  
  104.  
  105. desc
  106. @.
  107. @
  108.  
  109.  
  110. 1.16
  111. log
  112. @.
  113. @
  114. text
  115. @/*
  116.  * $Id: amiga.c 1.15 2000/12/17 10:10:14 olsen Exp olsen $
  117.  *
  118.  * :ts=4
  119.  *
  120.  * AmigaOS wrapper routines for Samba 2.0.0, using the AmiTCP V3 API
  121.  * and the SAS/C V6.58 compiler.
  122.  *
  123.  * Copyright (C) 1999-2000 by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>
  124.  *
  125.  * This program is free software; you can redistribute it and/or modify
  126.  * it under the terms of the GNU General Public License as published by
  127.  * the Free Software Foundation; either version 2 of the License, or
  128.  * (at your option) any later version.
  129.  *
  130.  * This program is distributed in the hope that it will be useful,
  131.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  132.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  133.  * GNU General Public License for more details.
  134.  *
  135.  * You should have received a copy of the GNU General Public License
  136.  * along with this program; if not, write to the Free Software
  137.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  138.  */
  139.  
  140. /******************************************************************************/
  141.  
  142. #include <bsdsocket/socketbasetags.h>
  143. #include <libraries/usergroup.h>
  144.  
  145. #include <intuition/intuition.h>
  146. #include <libraries/locale.h>
  147. #include <exec/execbase.h>
  148. #include <exec/memory.h>
  149. #include <dos/dosextens.h>
  150. #include <dos/dostags.h>
  151. #include <dos/rdargs.h>
  152. #include <devices/timer.h>
  153. #include <utility/date.h>
  154.  
  155. #include <clib/usergroup_protos.h>
  156. #include <clib/socket_protos.h>
  157.  
  158. #include <clib/intuition_protos.h>
  159. #include <clib/utility_protos.h>
  160. #include <clib/locale_protos.h>
  161. #include <clib/timer_protos.h>
  162. #include <clib/alib_protos.h>
  163. #include <clib/exec_protos.h>
  164. #include <clib/dos_protos.h>
  165.  
  166. #include <sys/socket.h>
  167. #include <sys/ioctl.h>
  168. #include <sys/time.h>
  169. #include <sys/dir.h>
  170.  
  171. #include <net/if.h>
  172.  
  173. #include <constructor.h>
  174. #include <stdarg.h>
  175. #include <stdlib.h>
  176. #include <string.h>
  177. #include <unistd.h>
  178. #include <signal.h>
  179. #include <utime.h>
  180. #include <errno.h>
  181. #include <stdio.h>
  182. #include <fcntl.h>
  183. #include <inetd.h>
  184. #include <stat.h>
  185. #include <ios1.h>
  186. #include <dos.h>
  187.  
  188. #include <pragmas/usergroup_pragmas.h>
  189. #include <pragmas/socket_pragmas.h>
  190.  
  191. #include <pragmas/exec_sysbase_pragmas.h>
  192. #include <pragmas/intuition_pragmas.h>
  193. #include <pragmas/utility_pragmas.h>
  194. #include <pragmas/locale_pragmas.h>
  195. #include <pragmas/timer_pragmas.h>
  196. #include <pragmas/dos_pragmas.h>
  197.  
  198. /******************************************************************************/
  199.  
  200. /* This is for the "iface_struct" definition. */
  201. #include "interfaces.h"
  202.  
  203. /******************************************************************************/
  204.  
  205. /*#define DEBUG*/
  206. #include "Assert.h"
  207.  
  208. /******************************************************************************/
  209.  
  210. STATIC VOID ReportProblem(const char *fmt, ...);
  211. STATIC VOID ForbidDOSCleanup(VOID);
  212. STATIC VOID PermitDOS(VOID);
  213. STATIC VOID ForbidDOS(VOID);
  214. STATIC VOID UnblockDescriptorCleanup(VOID);
  215. STATIC BOOL IsDescriptorNonblocking(int fd);
  216. STATIC VOID BlockDescriptor(int fd);
  217. STATIC VOID UnblockDescriptor(int fd);
  218. STATIC VOID SaveDescriptorCleanup(VOID);
  219. STATIC VOID RestoreDescriptor(struct UFB *ufb);
  220. STATIC BOOL SaveDescriptor(struct UFB *ufb);
  221. STATIC VOID UnmangleName(char **namePtr, struct MangleInfo *mi);
  222. STATIC int MangleName(char ** namePtr,struct MangleInfo * mi);
  223. STATIC VOID CloseUnlinkUnlockCleanup(VOID);
  224. STATIC VOID OpenDirCleanup(VOID);
  225. STATIC int TranslateRelativePath(char **namePtr, char *replace, int maxReplaceLen);
  226. STATIC VOID MapDescriptorSets(const fd_set *input_fds, int num_input_fds, fd_set *socket_fds, int *max_socket_fd_ptr, fd_set *file_fds, int *max_file_fd_ptr);
  227. STATIC VOID RemapDescriptorSets(const fd_set *socket_fds, int max_socket_fd, const fd_set *file_fds, int max_file_fd, fd_set *output_fds, int num_output_fds);
  228. STATIC VOID ConvertFileInfoToStat(struct MsgPort *port, struct FileInfoBlock *fib, struct stat *st);
  229. STATIC BOOL do_match(STRPTR str, STRPTR regexp);
  230. STATIC VOID nstrcpy_blank(const size_t maxSize, char *to, const char *from);
  231. STATIC BOOL SetFileSocket(FILE *stream, int sockfd);
  232. STATIC VOID DaemonInit(VOID);
  233. STATIC struct tm *ConvertTime(ULONG seconds);
  234. STATIC VOID MapIoErrToErrno(VOID);
  235. STATIC int MapFileNameAmigaToUnix(const char *amiga, char *unix, int maxUnixLen);
  236. STATIC VOID FlushSTDOUT(VOID);
  237. STATIC VOID CleanupSambaSemaphore(VOID);
  238. STATIC BOOL SetupSambaSemaphore(VOID);
  239. STATIC VOID RemoveLockedRegionNode(struct UFB *ufb, LONG start, LONG stop);
  240. STATIC VOID DeleteLockedRegionNode(struct LockedRegionNode *lrn);
  241. STATIC LONG CreateLockedRegionNode(struct LockedRegionNode **resultPtr);
  242. STATIC VOID DeleteFileLockNode(struct FileLockNode *fln);
  243. STATIC LONG CreateFileLockNode(struct UFB *ufb, struct FileLockNode **resultPtr);
  244. STATIC LONG FindFileLockNodeByFileHandle(BPTR fileHandle, struct FileLockNode **resultPtr);
  245. STATIC VOID FindFileLockNodeByDrawerAndName(BPTR parentDir, STRPTR fileName, struct FileLockNode **resultPtr);
  246. STATIC VOID CleanupFileLocks(int fd);
  247. STATIC int HandleFileLocking(int cmd, struct flock *l, struct UFB *ufb);
  248. STATIC struct LockedRegionNode *FindCollidingRegion(struct FileLockNode *fln, LONG start, LONG stop, BOOL shared);
  249.  
  250. /******************************************************************************/
  251.  
  252. int amiga_sigmask(int signum);
  253. int amiga_sigblock(int sigmask);
  254. int amiga_sigsetmask(int sigmask);
  255. int amiga_unlink(char *name);
  256. int amiga_open(char *name, int mode, int prot);
  257. int amiga_chdir(char *path);
  258. DIR *amiga_opendir(char *dirName);
  259. VOID amiga_closedir(DIR *dir);
  260. struct dirent *amiga_readdir(DIR *dir);
  261. int amiga_mkdir(char *name, int mode);
  262. int amiga_rmdir(char *name);
  263. int amiga_creat(char *name, int prot);
  264. FILE *amiga_fopen(char *name, char *mode);
  265. int amiga_rename(char *old, char *new);
  266. char *amiga_getcwd(char *buf, size_t size);
  267. int amiga_ftruncate(int fd, off_t size);
  268. int amiga_accept(int sockfd, struct sockaddr *cliaddr, int *addrlen);
  269. int amiga_bind(int sockfd, struct sockaddr *name, int namelen);
  270. int amiga_close(int fd);
  271. int amiga_connect(int sockfd, struct sockaddr *name, int namelen);
  272. int amiga_getpeername(int sockfd, struct sockaddr *name, int *namelen);
  273. int amiga_getsockopt(int sockfd, int level, int optname, VOID *optval, int *optlen);
  274. int amiga_ioctl(int fd, unsigned long request, char *arg);
  275. int amiga_listen(int sockfd, int backlog);
  276. int amiga_read(int fd, VOID *data, unsigned int size);
  277. int amiga_recvfrom(int sockfd, VOID *buff, int len, int flags, struct sockaddr *from, int *fromlen);
  278. int amiga_select(int num_fds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);
  279. int amiga_sendto(int sockfd, VOID *buff, int len, int flags, struct sockaddr *to, int tolen);
  280. int amiga_setsockopt(int sockfd, int level, int optname, VOID *optval, int optlen);
  281. int amiga_socket(int domain, int type, int protocol);
  282. int amiga_write(int fd, VOID *data, unsigned int size);
  283. int amiga_stat(char *name, struct stat *st);
  284. int amiga_lstat(char *name, struct stat *statstruct);
  285. int amiga_fstat(int fd, struct stat *st);
  286. int amiga_chmod(char *name, int mode);
  287. int amiga_dup(int fd);
  288. int amiga_dup2(int old_fd, int new_fd);
  289. int amiga_chown(char *name, uid_t uid, gid_t gid);
  290. int amiga_setegid(gid_t g);
  291. int amiga_seteuid(uid_t u);
  292. int amiga_gettimeofday(struct timeval *tv);
  293. int amiga_utime(char *name, struct utimbuf *time);
  294. VOID amiga_sleep(unsigned int seconds);
  295. char *amiga_crypt(char *key, char *salt);
  296. char *amiga_getpass(char *prompt);
  297. int amiga_setgid(gid_t id);
  298. int amiga_setgroups(int ngroups, gid_t *groups);
  299. gid_t amiga_getgid(VOID);
  300. struct group *amiga_getgrgid(gid_t gid);
  301. struct group *amiga_getgrnam(char *name);
  302. int amiga_getgroups(int ngroups, gid_t *groups);
  303. struct hostent *amiga_gethostbyaddr(char *addr, int len, int type);
  304. struct hostent *amiga_gethostbyname(char *name);
  305. struct netent *amiga_getnetbyname(char *name);
  306. int amiga_gethostname(char *hostname, int size);
  307. struct passwd *amiga_getpwnam(char *name);
  308. struct passwd *amiga_getpwuid(uid_t uid);
  309. uid_t amiga_getuid(VOID);
  310. gid_t amiga_getegid(VOID);
  311. uid_t amiga_geteuid(VOID);
  312. int amiga_initgroups(char *name, gid_t basegroup);
  313. int amiga_setuid(uid_t id);
  314. int amiga_umask(int mask);
  315. unsigned long amiga_inet_addr(char *addr);
  316. char *amiga_inet_ntoa(struct in_addr in);
  317. int amiga_getopt(int argc, char *argv[], char *opts);
  318. int amiga_system(char *cmd);
  319. int amiga_fork(VOID);
  320. VOID __tzset(VOID);
  321. time_t time(time_t *timeptr);
  322. struct tm *gmtime(const time_t *t);
  323. struct tm *localtime(const time_t *t);
  324. int amiga_strcasecmp(char *a, char *b);
  325. int amiga_strncasecmp(char *a, char *b, int len);
  326. VOID (*amiga_signal(int which,VOID (* action)(int)))(int);
  327. VOID amiga_alarm(int seconds);
  328. int amiga_waitpid(pid_t pid, int *status, int options);
  329. long amiga_setsid(VOID);
  330. int amiga_setreuid(uid_t real, uid_t eff);
  331. int amiga_setregid(gid_t real, gid_t eff);
  332. int amiga_fcntl(int fd, int cmd, unsigned long arg);
  333. int amiga_getsockname(int sockfd, struct sockaddr *name, int *namelen);
  334. int amiga_statfs(char *name, struct statfs *f);
  335. int amiga_execl(char *path, char *arg, ...);
  336. char *amiga_strerror(int error);
  337. int amiga_access(char *name, int modes);
  338. off_t amiga_lseek(int fd, off_t offset, int mode);
  339. int amiga_chroot(char *name);
  340. int amiga_kill(pid_t pid, int sig);
  341. pid_t amiga_getpid(VOID);
  342. int amiga_fgetc(FILE *in);
  343. char *amiga_fgets(char *str, int n, FILE *in);
  344. int amiga_fputs(const char *str, FILE *out);
  345. int amiga_puts(const char *str);
  346. int amiga_vfprintf(FILE *out, const char *fmt, va_list args);
  347. int amiga_fprintf(FILE *out, const char *fmt, ...);
  348. int amiga_printf(const char *fmt, ...);
  349. size_t amiga_fwrite(const void *data, size_t blockSize, size_t numBlocks, FILE *out);
  350. size_t amiga_fread(void *data, size_t blockSize, size_t numBlocks, FILE *in);
  351. int amiga_fclose(FILE *stream);
  352. int amiga_fflush(FILE *stream);
  353. int amiga_fseek(FILE *stream, long int offset, int mode);
  354. long int amiga_ftell(FILE *stream);
  355. int amiga_setvbuf(FILE *fp, char *buff, int type, size_t size);
  356. int amiga_fputc(int c,FILE *stream);
  357. VOID amiga_setbuf(FILE *stream,char *buffer);
  358.  
  359. /******************************************************************************/
  360.  
  361. VOID __regargs __chkabort(VOID);
  362. VOID _CXOVF(VOID);
  363. VOID __regargs _CXBRK(VOID);
  364.  
  365. /******************************************************************************/
  366.  
  367. /* These are in the Samba runtime library. */
  368. extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
  369. extern int snprintf (char *str, size_t count, const char *fmt, ...);
  370.  
  371. /******************************************************************************/
  372.  
  373. #define ZERO    ((BPTR)0L)
  374. #define ERROR    (-1)
  375. #define OK        (0)
  376. #define SAME    (0)
  377. #define NO        !
  378. #define NOT        !
  379. #define DONT    !
  380. #define CANNOT    !
  381. #define BUSY    (NULL)
  382. #define NO_FLAG    (0)
  383.  
  384. /******************************************************************************/
  385.  
  386. #define FLAG_IS_SET(v,f)    (((v) & (f)) == (f))
  387. #define FLAG_IS_CLEAR(v,f)    (((v) & (f)) == 0)
  388.  
  389. #define SET_FLAG(v,f)        (v |=  (f))
  390. #define CLEAR_FLAG(v,f)        (v &= ~(f))
  391.  
  392. /******************************************************************************/
  393.  
  394. #define STRING_IS_EMPTY(s)    (s[0] == '\0')
  395. #define NUM_ENTRIES(t)        (sizeof(t) / sizeof(t[0]))
  396.  
  397. /******************************************************************************/
  398.  
  399. #define FIB_IS_FILE(fib)    ((fib)->fib_DirEntryType < 0)
  400. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && \
  401.                              (fib)->fib_DirEntryType != ST_SOFTLINK)
  402.  
  403. /******************************************************************************/
  404.  
  405. /* This macro lets us long-align structures on the stack */
  406. #define D_S(type,name) \
  407.     char a_##name[sizeof(type)+3]; \
  408.     type *name = (type *)((LONG)(a_##name+3) & ~3)
  409.  
  410. /******************************************************************************/
  411.  
  412. #define UFB_IS_SOCKET        0x0800
  413. #define UFB_IS_NON_BLOCKING    0x1000
  414. #define UFB_UNLINK            0x2000
  415. #define UFB_LOCKED            0x4000
  416.  
  417. #define UNIX_TIME_OFFSET    252482400
  418.  
  419. #define MAX_BSTR_LEN        256
  420. #define MAX_FILENAME_LEN    512
  421. #define MAX_FFS_NAME_LEN    30
  422.  
  423. /******************************************************************************/
  424.  
  425. /* This is for ReadArgs(), to make the parameters a little more readable. */
  426. typedef unsigned char *    KEY;
  427. typedef long            SWITCH;
  428. typedef long *            NUMBER;
  429.  
  430. /******************************************************************************/
  431.  
  432. long __oslibversion = 37;
  433.  
  434. /******************************************************************************/
  435.  
  436. extern struct Library * SysBase;
  437. extern struct Library * DOSBase;
  438. extern struct Library * UtilityBase;
  439.  
  440. /******************************************************************************/
  441.  
  442. STATIC struct Device * TimerBase;
  443. STATIC struct MsgPort * TimerPort;
  444. STATIC struct timerequest * TimerRequest;
  445. STATIC LONG MinutesWest;
  446.  
  447. /******************************************************************************/
  448.  
  449. STATIC struct Library * SocketBase;
  450. STATIC struct Library * UserGroupBase;
  451.  
  452. /******************************************************************************/
  453.  
  454. /* Activate root mode, i.e. make getuid(), etc. return 0 instead of
  455.  * the 'real' user id.
  456.  */
  457. STATIC BOOL RootMode = FALSE;
  458.  
  459. /******************************************************************************/
  460.  
  461. #if defined(_M68020) && defined(_M68881)
  462. #define MACHINE_TYPE "['020+FPU]"
  463. #elif defined(_M68020)
  464. #define MACHINE_TYPE "['020]"
  465. #else
  466. #define MACHINE_TYPE "[68k]"
  467. #endif
  468.  
  469. /******************************************************************************/
  470.  
  471. #include "Amiga_Samba_rev.h"
  472. char * VersionTag = VERSTAG " " MACHINE_TYPE " Samba version 2.0.0 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  473.  
  474. /******************************************************************************/
  475.  
  476. /* This is for backwards compatibility with Kickstart 2.04 and
  477.  * avoids a deadlock when trying to get a shared lock on
  478.  * a semaphore already held in exclusive mode by the same Task.
  479.  */
  480. STATIC VOID
  481. SafeObtainSemaphoreShared(struct SignalSemaphore * semaphore)
  482. {
  483.     /* Do it right with Kickstart 3.x. */
  484.     if(SysBase->lib_Version >= 39)
  485.     {
  486.         ObtainSemaphoreShared(semaphore);
  487.     }
  488.     else
  489.     {
  490.         /* Try to get the shared semaphore */
  491.         if(CANNOT AttemptSemaphoreShared(semaphore))
  492.         {
  493.             /* Check if we can get the exclusive version */
  494.             if(CANNOT AttemptSemaphore(semaphore))
  495.             {
  496.                 /* Oh well, wait for the shared lock */
  497.                 ObtainSemaphoreShared(semaphore);
  498.             }
  499.         }
  500.     }
  501. }
  502.  
  503. /******************************************************************************/
  504.  
  505. STATIC BOOL AllowBreak = TRUE;
  506.  
  507. STATIC BOOL
  508. CheckAbort(VOID)
  509. {
  510.     BOOL result;
  511.  
  512.     result = (BOOL)(AllowBreak && FLAG_IS_SET(SetSignal(0,SIGBREAKF_CTRL_C),SIGBREAKF_CTRL_C));
  513.  
  514.     return(result);
  515. }
  516.  
  517. VOID __regargs
  518. __chkabort(VOID)
  519. {
  520.     if(CheckAbort())
  521.         raise(SIGINT);
  522. }
  523.  
  524. int
  525. amiga_sigmask(int signum)
  526. {
  527.     int result = 0;
  528.  
  529.     ENTER();
  530.  
  531.     SHOWVALUE(signum);
  532.  
  533.     if(signum == SIGTERM || signum == SIGINT)
  534.         result = (1<<SIGINT);
  535.  
  536.     RETURN(result);
  537.     return(result);
  538. }
  539.  
  540. int
  541. amiga_sigblock(int sigmask)
  542. {
  543.     BOOL oldAllowBreak = AllowBreak;
  544.     int result = 0;
  545.  
  546.     ENTER();
  547.  
  548.     SHOWVALUE(sigmask);
  549.  
  550.     if(DONT AllowBreak)
  551.         result = (1<<SIGINT);
  552.  
  553.     if(FLAG_IS_SET(sigmask,(1<<SIGINT)))
  554.     {
  555.         AllowBreak = FALSE;
  556.  
  557.         if(oldAllowBreak != AllowBreak)
  558.         {
  559.             SocketBaseTags(
  560.                 SBTM_SETVAL(SBTC_BREAKMASK),NO_FLAG,
  561.             TAG_END);
  562.         }
  563.     }
  564.  
  565.     RETURN(result);
  566.     return(result);
  567. }
  568.  
  569. int
  570. amiga_sigsetmask(int sigmask)
  571. {
  572.     BOOL oldAllowBreak = AllowBreak;
  573.     int result = 0;
  574.  
  575.     ENTER();
  576.  
  577.     SHOWVALUE(sigmask);
  578.  
  579.     AllowBreak = FLAG_IS_CLEAR(sigmask,(1<<SIGINT));
  580.     if(oldAllowBreak != AllowBreak)
  581.     {
  582.         ULONG mask;
  583.  
  584.         if(AllowBreak)
  585.             mask = SIGBREAKF_CTRL_C;
  586.         else
  587.             mask = NO_FLAG;
  588.  
  589.         SocketBaseTags(
  590.             SBTM_SETVAL(SBTC_BREAKMASK),mask,
  591.         TAG_END);
  592.     }
  593.  
  594.     RETURN(result);
  595.     return(result);
  596. }
  597.  
  598. /******************************************************************************/
  599.  
  600. STATIC VOID
  601. ReportProblem(const char *fmt,...)
  602. {
  603.     extern const STRPTR _ProgramName;
  604.     BOOL useRequester = TRUE;
  605.     va_list varArgs;
  606.  
  607.     ASSERT(fmt != NULL);
  608.  
  609.     va_start(varArgs,fmt);
  610.  
  611.     /* Launched from Workbench? */
  612.     if(WBenchMsg == NULL)
  613.     {
  614.         if(DOSBase->lib_Version >= 37)
  615.         {
  616.             BPTR stream;
  617.  
  618.             /* Make a copy of the current terminal
  619.              * output stream. This avoids sending
  620.              * an error message through a redirected
  621.              * standard output stream, the output
  622.              * will go straight to the terminal.
  623.              */
  624.             stream = Open("CONSOLE:",MODE_NEWFILE);
  625.             if(stream != ZERO)
  626.             {
  627.                 struct FileHandle * fh = BADDR(stream);
  628.  
  629.                 /* Check if the output was redirected
  630.                  * to "NIL:"; if not, print the error
  631.                  * error message.
  632.                  */
  633.                 if(fh->fh_Type != NULL)
  634.                 {
  635.                     FPrintf(stream,"%s: ",_ProgramName);
  636.                     VFPrintf(stream,(STRPTR)fmt,(APTR)varArgs);
  637.                     FPrintf(stream,"\a\n");
  638.  
  639.                     useRequester = FALSE;
  640.                 }
  641.  
  642.                 Close(stream);
  643.             }
  644.         }
  645.     }
  646.  
  647.     /* Oh well, don't use the Shell for output. Put up a
  648.      * requester.
  649.      */
  650.     if(useRequester)
  651.     {
  652.         struct Library * IntuitionBase;
  653.  
  654.         IntuitionBase = OpenLibrary("intuition.library",37);
  655.         if(IntuitionBase != NULL)
  656.         {
  657.             struct Window * reqWindow;
  658.             struct EasyStruct es;
  659.             char title[100];
  660.  
  661.             snprintf(title,sizeof(title)-1,"Amiga Samba Error (%s)",FilePart(_ProgramName));
  662.             title[sizeof(title)-1] = '\0';
  663.  
  664.             memset(&es,0,sizeof(es));
  665.  
  666.             es.es_StructSize    = sizeof(es);
  667.             es.es_Title            = (STRPTR)title;
  668.             es.es_TextFormat    = (STRPTR)fmt;
  669.             es.es_GadgetFormat    = "Ok";
  670.  
  671.             reqWindow = BuildEasyRequestArgs(NULL,&es,0,(APTR)varArgs);
  672.             if(reqWindow != NULL && reqWindow != (struct Window *)1)
  673.             {
  674.                 struct timerequest * timeRequest = NULL;
  675.                 struct MsgPort * timePort;
  676.                 BOOL timerOpen = FALSE;
  677.                 ULONG windowSignal;
  678.                 ULONG timerSignal;
  679.                 ULONG signals;
  680.                 BOOL done;
  681.  
  682.                 timePort = CreateMsgPort();
  683.                 if(timePort != NULL)
  684.                 {
  685.                     timeRequest = CreateIORequest(timePort,sizeof(*timeRequest));
  686.                     if(timeRequest != NULL)
  687.                     {
  688.                         if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timeRequest,0) == OK)
  689.                             timerOpen = TRUE;
  690.                     }
  691.                 }
  692.  
  693.                 windowSignal = (1UL << reqWindow->UserPort->mp_SigBit);
  694.  
  695.                 if(timerOpen)
  696.                 {
  697.                     timerSignal = (1UL << timePort->mp_SigBit);
  698.  
  699.                     timeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  700.                     timeRequest->tr_time.tv_secs    = 30;
  701.                     timeRequest->tr_time.tv_micro    = 0;
  702.  
  703.                     SendIO((struct IORequest *)timeRequest);
  704.                 }
  705.                 else
  706.                 {
  707.                     timerSignal = 0;
  708.                 }
  709.  
  710.                 DisplayBeep(reqWindow->WScreen);
  711.  
  712.                 done = FALSE;
  713.                 do
  714.                 {
  715.                     signals = Wait(windowSignal | timerSignal);
  716.  
  717.                     if(FLAG_IS_SET(signals,windowSignal))
  718.                     {
  719.                         if(SysReqHandler(reqWindow,NULL,FALSE) >= 0)
  720.                             done = TRUE;
  721.                     }
  722.  
  723.                     if(FLAG_IS_SET(signals,timerSignal))
  724.                     {
  725.                         done = TRUE;
  726.                     }
  727.                 }
  728.                 while(NOT done);
  729.  
  730.                 if(timerOpen)
  731.                 {
  732.                     if(CheckIO((struct IORequest *)timeRequest) == BUSY)
  733.                         AbortIO((struct IORequest *)timeRequest);
  734.  
  735.                     WaitIO((struct IORequest *)timeRequest);
  736.  
  737.                     CloseDevice((struct IORequest *)timeRequest);
  738.                 }
  739.  
  740.                 DeleteIORequest((struct IORequest *)timeRequest);
  741.                 DeleteMsgPort(timePort);
  742.  
  743.                 FreeSysRequest(reqWindow);
  744.             }
  745.  
  746.             CloseLibrary(IntuitionBase);
  747.         }
  748.     }
  749.  
  750.     va_end(varArgs);
  751. }
  752.  
  753. /******************************************************************************/
  754.  
  755. STATIC APTR OldWindowPtr;
  756. STATIC LONG ForbidCount;
  757.  
  758. STATIC VOID
  759. ForbidDOSCleanup(VOID)
  760. {
  761.     if(ForbidCount > 0)
  762.     {
  763.         struct Process * pr = (struct Process *)FindTask(NULL);
  764.  
  765.         pr->pr_WindowPtr = OldWindowPtr;
  766.  
  767.         ForbidCount = 0;
  768.     }
  769. }
  770.  
  771. STATIC VOID
  772. PermitDOS(VOID)
  773. {
  774.     ASSERT(ForbidCount > 0);
  775.  
  776.     if(--ForbidCount == 0)
  777.     {
  778.         struct Process * pr = (struct Process *)FindTask(NULL);
  779.  
  780.         pr->pr_WindowPtr = OldWindowPtr;
  781.     }
  782. }
  783.  
  784. STATIC VOID
  785. ForbidDOS(VOID)
  786. {
  787.     if(ForbidCount++ == 0)
  788.     {
  789.         struct Process * pr = (struct Process *)FindTask(NULL);
  790.  
  791.         OldWindowPtr = pr->pr_WindowPtr;
  792.         pr->pr_WindowPtr = (APTR)-1;
  793.     }
  794. }
  795.  
  796. /******************************************************************************/
  797.  
  798. #define SINGLE_CHARACTER_MODE    (1)
  799. #define BUFFERED_MODE            (0)
  800.  
  801. STATIC int MaxNonblockingDescriptor = -1;
  802.  
  803. STATIC VOID
  804. UnblockDescriptorCleanup(VOID)
  805. {
  806.     struct UFB * ufb;
  807.     int fd;
  808.  
  809.     /* We look for descriptors we switched into
  810.      * non-blocking mode and reset them back
  811.      * to blocking mode.
  812.      */
  813.     for(fd = 0 ; fd <= MaxNonblockingDescriptor ; fd++)
  814.     {
  815.         ufb = chkufb(fd);
  816.         if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  817.         {
  818.             SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  819.  
  820.             CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  821.         }
  822.     }
  823. }
  824.  
  825. STATIC BOOL
  826. IsDescriptorNonblocking(int fd)
  827. {
  828.     struct UFB * ufb;
  829.     BOOL result = FALSE;
  830.  
  831.     /* Verify if a descriptor was switched into non-blocking mode. */
  832.     ufb = chkufb(fd);
  833.     if(ufb != NULL)
  834.         result = FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  835.  
  836.     return(result);
  837. }
  838.  
  839. STATIC VOID
  840. BlockDescriptor(int fd)
  841. {
  842.     struct UFB * ufb;
  843.  
  844.     /* This resets a file descriptor to blocking mode,
  845.      * once it has been set to blocking mode.
  846.      */
  847.     ufb = chkufb(fd);
  848.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  849.     {
  850.         SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  851.  
  852.         CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  853.     }
  854. }
  855.  
  856. STATIC VOID
  857. UnblockDescriptor(int fd)
  858. {
  859.     struct UFB * ufb;
  860.  
  861.     ufb = chkufb(fd);
  862.     if(ufb != NULL)
  863.     {
  864.         /* Make sure we got a file and it's not already
  865.          * in non-blocking mode.
  866.          */
  867.         if(FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET) && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  868.         {
  869.             /* Try to flip it into single character mode,
  870.              * which we treat as "non-blocking" mode.
  871.              */
  872.             if(SetMode((BPTR)ufb->ufbfh,SINGLE_CHARACTER_MODE))
  873.             {
  874.                 SET_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  875.  
  876.                 /* Remember which one we switched. */
  877.                 if(MaxNonblockingDescriptor < fd)
  878.                     MaxNonblockingDescriptor = fd;
  879.             }
  880.         }
  881.     }
  882. }
  883.  
  884. /******************************************************************************/
  885.  
  886. struct SavedDescriptorNode
  887. {
  888.     struct MinNode    sdn_MinNode;
  889.     struct UFB *    sdn_UFB;
  890.     BPTR            sdn_FileHandle;
  891. };
  892.  
  893. STATIC BOOL DescriptorListInitialized = FALSE;
  894. STATIC struct List DescriptorList;
  895.  
  896. STATIC VOID
  897. SaveDescriptorCleanup(VOID)
  898. {
  899.     /* This routine restores all file descriptors
  900.      * we used to map to sockets to use proper file
  901.      * handles.
  902.      */
  903.     if(DescriptorListInitialized)
  904.     {
  905.         struct SavedDescriptorNode * sdn;
  906.  
  907.         for(sdn = (struct SavedDescriptorNode *)DescriptorList.lh_Head ;
  908.             sdn->sdn_MinNode.mln_Succ != NULL ;
  909.             sdn = (struct SavedDescriptorNode *)sdn->sdn_MinNode.mln_Succ)
  910.         {
  911.             /* Make sure that if this file is bound to
  912.              * a socket, the socket is closed.
  913.              */
  914.             if(FLAG_IS_SET(sdn->sdn_UFB->ufbflg,UFB_IS_SOCKET))
  915.             {
  916.                 CloseSocket(sdn->sdn_UFB->ufbfh);
  917.  
  918.                 CLEAR_FLAG(sdn->sdn_UFB->ufbflg,UFB_IS_SOCKET);
  919.             }
  920.  
  921.             sdn->sdn_UFB->ufbfh = sdn->sdn_FileHandle;
  922.         }
  923.     }
  924. }
  925.  
  926. STATIC VOID
  927. RestoreDescriptor(struct UFB * ufb)
  928. {
  929.     ASSERT(ufb != NULL);
  930.  
  931.     /* This routine restores one particular file descriptor
  932.      * which was used as a socket to refer to a proper
  933.      * file handle.
  934.      */
  935.     if(DescriptorListInitialized)
  936.     {
  937.         struct SavedDescriptorNode * sdn;
  938.  
  939.         for(sdn = (struct SavedDescriptorNode *)DescriptorList.lh_Head ;
  940.             sdn->sdn_MinNode.mln_Succ != NULL ;
  941.             sdn = (struct SavedDescriptorNode *)sdn->sdn_MinNode.mln_Succ)
  942.         {
  943.             if(sdn->sdn_UFB == ufb)
  944.             {
  945.                 sdn->sdn_UFB->ufbfh = sdn->sdn_FileHandle;
  946.  
  947.                 Remove((struct Node *)sdn);
  948.                 free(sdn);
  949.  
  950.                 break;
  951.             }
  952.         }
  953.     }
  954. }
  955.  
  956. STATIC BOOL
  957. SaveDescriptor(struct UFB * ufb)
  958. {
  959.     struct SavedDescriptorNode * sdn;
  960.     BOOL result = FALSE;
  961.  
  962.     ASSERT(ufb != NULL);
  963.  
  964.     /* Set up the descriptor list, unless it's already
  965.      * initialized.
  966.      */
  967.     if(NOT DescriptorListInitialized)
  968.     {
  969.         NewList(&DescriptorList);
  970.         DescriptorListInitialized = TRUE;
  971.     }
  972.  
  973.     sdn = malloc(sizeof(*sdn));
  974.     if(sdn != NULL)
  975.     {
  976.         memset(sdn,0,sizeof(*sdn));
  977.  
  978.         /* Remember the file buffer and the file
  979.          * handle attached to the descriptor.
  980.          */
  981.         sdn->sdn_UFB        = ufb;
  982.         sdn->sdn_FileHandle    = ufb->ufbfh;
  983.  
  984.         AddHead(&DescriptorList,(struct Node *)sdn);
  985.  
  986.         result = TRUE;
  987.     }
  988.  
  989.     return(result);
  990. }
  991.  
  992. /******************************************************************************/
  993.  
  994. STATIC BOOL InitialCurrentDirInitialized = FALSE;
  995. STATIC BPTR InitialCurrentDir;
  996. STATIC BPTR ChangedCurrentDir;
  997.  
  998. CBMLIB_DESTRUCTOR(CloseLibsAndDevs)
  999. {
  1000.     ENTER();
  1001.  
  1002.     /* Return to the directory we were in
  1003.      * when we started.
  1004.      */
  1005.     if(InitialCurrentDirInitialized)
  1006.     {
  1007.         CurrentDir(InitialCurrentDir);
  1008.         InitialCurrentDirInitialized = FALSE;
  1009.     }
  1010.  
  1011.     /* If the current directory was changed, unlock it. */
  1012.     if(ChangedCurrentDir != ZERO)
  1013.     {
  1014.         UnLock(ChangedCurrentDir);
  1015.         ChangedCurrentDir = ZERO;
  1016.     }
  1017.  
  1018.     CleanupSambaSemaphore();
  1019.  
  1020.     if(TimerRequest != NULL)
  1021.     {
  1022.         if(TimerRequest->tr_node.io_Device != NULL)
  1023.             CloseDevice((struct IORequest *)TimerRequest);
  1024.  
  1025.         DeleteIORequest((struct IORequest *)TimerRequest);
  1026.         TimerRequest = NULL;
  1027.     }
  1028.  
  1029.     if(TimerPort != NULL)
  1030.     {
  1031.         DeleteMsgPort(TimerPort);
  1032.         TimerPort = NULL;
  1033.     }
  1034.  
  1035.     TimerBase = NULL;
  1036.  
  1037.     if(SocketBase != NULL)
  1038.     {
  1039.         CloseLibrary(SocketBase);
  1040.         SocketBase = NULL;
  1041.     }
  1042.  
  1043.     if(UserGroupBase != NULL)
  1044.     {
  1045.         CloseLibrary(UserGroupBase);
  1046.         UserGroupBase = NULL;
  1047.     }
  1048.  
  1049.     LEAVE();
  1050. }
  1051.  
  1052. CBMLIB_CONSTRUCTOR(OpenLibsAndDevs)
  1053. {
  1054.     extern STRPTR _ProgramName;
  1055.     BOOL sambaSemaphoreCreated;
  1056.     struct LocaleBase * LocaleBase;
  1057.     char *timerError = "";
  1058.     BPTR sambaLock;
  1059.     UBYTE env_buffer[256];
  1060.     int result = ERROR;
  1061.  
  1062.     SETPROGRAMNAME(_ProgramName);
  1063.     SETDEBUGLEVEL(0);
  1064.  
  1065.     ENTER();
  1066.  
  1067.     SocketBase = OpenLibrary("bsdsocket.library",3);
  1068.     UserGroupBase = OpenLibrary("usergroup.library",1);
  1069.  
  1070.     if(SysBase->lib_Version >= 37)
  1071.     {
  1072.         TimerPort = CreateMsgPort();
  1073.         if(TimerPort != NULL)
  1074.         {
  1075.             TimerRequest = (struct timerequest *)CreateIORequest(TimerPort,sizeof(*TimerRequest));
  1076.             if(TimerRequest != NULL)
  1077.             {
  1078.                 if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerRequest,NULL) == OK)
  1079.                     TimerBase = TimerRequest->tr_node.io_Device;
  1080.                 else
  1081.                     timerError = "opening \"timer.device\"";
  1082.             }
  1083.             else
  1084.             {
  1085.                 timerError = "creating timer I/O request";
  1086.             }
  1087.         }
  1088.         else
  1089.         {
  1090.             timerError = "creating timer message port";
  1091.         }
  1092.     }
  1093.  
  1094.     /* Try to determine this machine's time zone. */
  1095.     LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38);
  1096.     if(LocaleBase != NULL)
  1097.     {
  1098.         struct Locale * locale;
  1099.  
  1100.         locale = OpenLocale(NULL);
  1101.         MinutesWest = locale->loc_GMTOffset;
  1102.         CloseLocale(locale);
  1103.  
  1104.         CloseLibrary((struct Library *)LocaleBase);
  1105.     }
  1106.  
  1107.     ForbidDOS();
  1108.  
  1109.     /* Try to get a lock on the "Samba:" directory,
  1110.      * just to make sure the assignment is in place.
  1111.      */
  1112.     sambaLock = Lock("Samba:",SHARED_LOCK);
  1113.     if(sambaLock != ZERO)
  1114.         UnLock(sambaLock);
  1115.  
  1116.     PermitDOS();
  1117.  
  1118.     /* Initialize the global process ID database. */
  1119.     sambaSemaphoreCreated = SetupSambaSemaphore();
  1120.  
  1121.     if(SocketBase != NULL && UserGroupBase != NULL && TimerBase != NULL &&
  1122.        sambaLock != ZERO && sambaSemaphoreCreated)
  1123.     {
  1124.         STATIC long h_errno = 0;
  1125.         struct timeval now;
  1126.         int error;
  1127.  
  1128.         error = SocketBaseTags(
  1129.             SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),    &errno,
  1130.             SBTM_SETVAL(SBTC_HERRNOLONGPTR),            &h_errno,
  1131.             SBTM_SETVAL(SBTC_LOGTAGPTR),                _ProgramName,
  1132.             SBTM_SETVAL(SBTC_BREAKMASK),                SIGBREAKF_CTRL_C,
  1133.         TAG_END);
  1134.         if(error != OK)
  1135.         {
  1136.             ReportProblem("Error initializing socket data (error=%ld).",error);
  1137.             goto out;
  1138.         }
  1139.  
  1140.         error = ug_SetupContextTags(_ProgramName,
  1141.             UGT_ERRNOPTR(sizeof(errno)),&errno,
  1142.         TAG_END);
  1143.         if(error != OK)
  1144.         {
  1145.             ReportProblem("Error initializing user group data (error=%ld).",error);
  1146.             goto out;
  1147.         }
  1148.  
  1149.         /* Use a new random number seed. */
  1150.         GetSysTime((APTR)&now);
  1151.         srand(now.tv_secs);
  1152.     }
  1153.     else
  1154.     {
  1155.         if(SocketBase == NULL)
  1156.             ReportProblem("Error opening \"bsdsocket.library\" V3.");
  1157.         else if (UserGroupBase == NULL)
  1158.             ReportProblem("Error opening \"usergroup.library\" V1.");
  1159.         else if (TimerBase == NULL)
  1160.             ReportProblem("Error %s.",timerError);
  1161.         else if (sambaLock == ZERO)
  1162.             ReportProblem("Error finding \"Samba:\" assignment.");
  1163.         else if (NOT sambaSemaphoreCreated)
  1164.             ReportProblem("Error creating Samba semaphore.");
  1165.  
  1166.         goto out;
  1167.     }
  1168.  
  1169.     /* Now try to read any global options that may be set. */
  1170.     if(GetVar("Samba",env_buffer,sizeof(env_buffer)-1,GVF_GLOBAL_ONLY) > 0)
  1171.     {
  1172.         struct RDArgs * rda;
  1173.  
  1174.         rda = (struct RDArgs *)AllocDosObjectTagList(DOS_RDARGS,NULL);
  1175.         if(rda != NULL)
  1176.         {
  1177.             struct
  1178.             {
  1179.                 SWITCH RootMode;
  1180.             } cmd_args;
  1181.  
  1182.             STRPTR cmd_template =
  1183.                 "ROOT/S";
  1184.  
  1185.             strcat(env_buffer,"\n");
  1186.  
  1187.             rda->RDA_Source.CS_Buffer = env_buffer;
  1188.             rda->RDA_Source.CS_Length = strlen(env_buffer);
  1189.             rda->RDA_Source.CS_CurChr = 0;
  1190.             rda->RDA_Flags |= RDAF_NOPROMPT;
  1191.  
  1192.             memset(&cmd_args,0,sizeof(cmd_args));
  1193.  
  1194.             if(ReadArgs(cmd_template,(LONG *)&cmd_args,rda))
  1195.             {
  1196.                 if(cmd_args.RootMode)
  1197.                     RootMode = TRUE;
  1198.  
  1199.                 FreeArgs(rda);
  1200.             }
  1201.  
  1202.             FreeDosObject(DOS_RDARGS,rda);
  1203.         }
  1204.     }
  1205.  
  1206.     /* Initialize the current time zone variable. */
  1207.     __tzset();
  1208.  
  1209.     result = OK;
  1210.  
  1211. out:
  1212.  
  1213.     RETURN(result);
  1214.     return(result);
  1215. }
  1216.  
  1217. /******************************************************************************/
  1218.  
  1219. DESTRUCTOR_P(SocketExit,501)
  1220. {
  1221.     ENTER();
  1222.  
  1223.     SaveDescriptorCleanup();
  1224.     UnblockDescriptorCleanup();
  1225.     CloseUnlinkUnlockCleanup();
  1226.     ForbidDOSCleanup();
  1227.  
  1228.     LEAVE();
  1229. }
  1230.  
  1231. /******************************************************************************/
  1232.  
  1233. CONSTRUCTOR_P(DaemonInit,501)
  1234. {
  1235.     ENTER();
  1236.  
  1237.     DaemonInit();
  1238.  
  1239.     RETURN(0);
  1240.     return(0);
  1241. }
  1242.  
  1243. /******************************************************************************/
  1244.  
  1245. struct MangleInfo
  1246. {
  1247.     char    mi_Substitute[MAX_FILENAME_LEN];
  1248.     char *    mi_OldName;
  1249. };
  1250.  
  1251. STATIC VOID
  1252. UnmangleName(char ** namePtr,struct MangleInfo * mi)
  1253. {
  1254.     /* Reset the name pointer to its previous position. */
  1255.     (*namePtr) = mi->mi_OldName;
  1256. }
  1257.  
  1258. STATIC int
  1259. MangleName(char ** namePtr,struct MangleInfo * mi)
  1260. {
  1261.     char * name = (*namePtr);
  1262.     int result = ERROR;
  1263.  
  1264.     ENTER();
  1265.  
  1266.     SHOWSTRING(name);
  1267.  
  1268.     if(TranslateRelativePath(&name,mi->mi_Substitute,sizeof(mi->mi_Substitute)) == OK)
  1269.     {
  1270.         char * replace = mi->mi_Substitute;
  1271.         int len,i;
  1272.  
  1273.         SHOWSTRING(name);
  1274.  
  1275.         len = strlen(name);
  1276.  
  1277.         /* If there is one, strip the trailing slash. */
  1278.         if(len > 1 && name[len-1] == '/')
  1279.         {
  1280.             SHOWMSG("trailing slash");
  1281.  
  1282.             if(name != replace)
  1283.             {
  1284.                 strcpy(replace,name);
  1285.                 name = replace;
  1286.             }
  1287.  
  1288.             name[--len] = '\0';
  1289.         }
  1290.  
  1291.         if(strcmp(name,".") == SAME)
  1292.         {
  1293.             SHOWMSG("dot file");
  1294.  
  1295.             /* Convert to current directory. */
  1296.             name = "";
  1297.         }
  1298.         else if (strcmp(name,"..") == SAME)
  1299.         {
  1300.             SHOWMSG("dot dot file");
  1301.  
  1302.             /* Convert to parent directory. */
  1303.             name = "/";
  1304.         }
  1305.         else if (strncmp(name,"./",2) == SAME)
  1306.         {
  1307.             SHOWMSG("reference to local dir");
  1308.  
  1309.             /* Retain just the name. */
  1310.             name += 2;
  1311.         }
  1312.         else if (strncmp(name,"../",3) == SAME)
  1313.         {
  1314.             SHOWMSG("reference to parent dir");
  1315.  
  1316.             /* Convert to parent directory. */
  1317.             name += 2;
  1318.         }
  1319.         else if (strncmp(name,"/",1) == SAME)
  1320.         {
  1321.             SHOWMSG("root dir");
  1322.  
  1323.             /* Ok, so this is an absolute path. We first
  1324.              * check for a few special cases, the first
  1325.              * being a reference to "/tmp".
  1326.              */
  1327.             if(Strnicmp(name,"/tmp",4) == SAME && (name[4] == '/' || name[4] == '\0'))
  1328.             {
  1329.                 SHOWMSG("tmp");
  1330.  
  1331.                 if(name[4] == '/')
  1332.                 {
  1333.                     /* Convert "/tmp/foo" to "T:foo". */
  1334.                     strcpy(replace,"T:");
  1335.                     memmove(&replace[2],&name[5],strlen(&name[5])+1);
  1336.                 }
  1337.                 else
  1338.                 {
  1339.                     /* Convert "/tmp" to "T:". */
  1340.                     strcpy(replace,"T:");
  1341.                 }
  1342.  
  1343.                 name = replace;
  1344.             }
  1345.             else if(Strnicmp(name,"/dev/",5) == SAME)
  1346.             {
  1347.                 SHOWMSG("dev");
  1348.  
  1349.                 /* Except for "/dev/null" all references to
  1350.                  * files in "/dev" are redirected to nonexistant
  1351.                  * files. Note that this relies upon the fact
  1352.                  * that "NIL:" is not a true device.
  1353.                  */
  1354.                 if(Stricmp(name,"/dev/null") == SAME)
  1355.                     name = "NIL:";
  1356.                 else
  1357.                     name = "NIL:this_file_never_opens";
  1358.             }
  1359.             else
  1360.             {
  1361.                 int i,rest = 0,len = 0;
  1362.  
  1363.                 SHOWMSG("absolute");
  1364.  
  1365.                 /* Find out how long the first component
  1366.                  * of the absolute path is.
  1367.                  */
  1368.                 for(i = 1 ; i <= strlen(name) ; i++)
  1369.                 {
  1370.                     if(name[i] == '/' || name[i] == '\0')
  1371.                     {
  1372.                         len = i-1;
  1373.  
  1374.                         /* Is there anything following
  1375.                          * the path name?
  1376.                          */
  1377.                         if(name[i] == '/')
  1378.                             rest = i+1;
  1379.  
  1380.                         break;
  1381.                     }
  1382.                 }
  1383.  
  1384.                 /* Copy the first component and
  1385.                  * attach a colon. "/foo" becomes
  1386.                  * "foo:" (without the trailing NUL
  1387.                  * byte, this will get attached
  1388.                  * later).
  1389.                  */
  1390.                 memmove(replace,&name[1],len);
  1391.                 replace[len++] = ':';
  1392.  
  1393.                 /* Now add the finishing touches. "/foo/bar" finally
  1394.                  * becomes "foo:bar" and "/foo" becomes "foo:" with the
  1395.                  * trailing NUL byte attached.
  1396.                  */
  1397.                 if(rest > 0)
  1398.                     memmove(&replace[len],&name[rest],strlen(&name[rest])+1);
  1399.                 else
  1400.                     replace[len] = '\0';
  1401.  
  1402.                 name = replace;
  1403.             }
  1404.         }
  1405.  
  1406.         SHOWSTRING(name);
  1407.  
  1408.         /* Convert any "./" or "../" embedded in the name
  1409.          * if necessary.
  1410.          */
  1411.         SHOWMSG("stripping embedded slashes");
  1412.         for(i = 0 ; i < strlen(name) ; i++)
  1413.         {
  1414.             if(strncmp(&name[i],"./",2) == SAME ||
  1415.                strncmp(&name[i],"../",3) == SAME)
  1416.             {
  1417.                 char * from    = name;
  1418.                 char * to    = replace;
  1419.  
  1420.                 name = replace;
  1421.  
  1422.                 while((*from) != '\0')
  1423.                 {
  1424.                     if((*from) == '.')
  1425.                     {
  1426.                         if(from[1] == '/' || from[1] == '\0')
  1427.                         {
  1428.                             /* "."  -> "" (done)
  1429.                              * "./" -> "" (continue)
  1430.                              */
  1431.                             if(from[1] == '\0')
  1432.                                 break;
  1433.                             else
  1434.                                 from += 2;
  1435.                         }
  1436.                         else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0'))
  1437.                         {
  1438.                             /* ".."  -> "/" (done)
  1439.                              * "../" -> "/" (continue)
  1440.                              */
  1441.                             (*to++) = '/';
  1442.  
  1443.                             if(from[2] == '\0')
  1444.                                 break;
  1445.                             else
  1446.                                 from += 3;
  1447.                         }
  1448.                         else
  1449.                         {
  1450.                             (*to++) = (*from++);
  1451.                         }
  1452.                     }
  1453.                     else
  1454.                     {
  1455.                         (*to++) = (*from++);
  1456.                     }
  1457.                 }
  1458.  
  1459.                 (*to) = '\0';
  1460.  
  1461.                 break;
  1462.             }
  1463.         }
  1464.  
  1465.         /* Reduce any "//" embedded in the name if
  1466.          * necessary.
  1467.          */
  1468.         SHOWMSG("stripping more embedded slashes");
  1469.         for(i = 0 ; i < ((int)strlen(name))-1 ; i++)
  1470.         {
  1471.             if(name[i] == '/' && name[i+1] == '/')
  1472.             {
  1473.                 int position,len;
  1474.  
  1475.                 if(name != replace)
  1476.                 {
  1477.                     strcpy(replace,name);
  1478.                     name = replace;
  1479.                 }
  1480.  
  1481.                 len = strlen(name);
  1482.  
  1483.                 position = len - 1;
  1484.                 while(position > 1 && name[position] != ':')
  1485.                 {
  1486.                     /* "foo/bar//baz" -> "foo/baz" */
  1487.                     if(name[position] == '/' && name[position-1] == '/')
  1488.                     {
  1489.                         int componentLen;
  1490.  
  1491.                         /* Move in front of the name component preceding the "//". */
  1492.                         componentLen = 0;
  1493.                         for(i = position - 2 ; i > 0 && name[i] != ':' && name[i] != '/' ; i--)
  1494.                             componentLen++;
  1495.  
  1496.                         if(componentLen > 0)
  1497.                         {
  1498.                             memmove(&name[position - (componentLen + 1)],&name[position + 1],len - (position + 1));
  1499.  
  1500.                             len -= componentLen + 2;
  1501.                             name[len] = '\0';
  1502.  
  1503.                             position -= componentLen + 1;
  1504.                         }
  1505.                     }
  1506.  
  1507.                     position--;
  1508.                 }
  1509.  
  1510.                 break;
  1511.             }
  1512.         }
  1513.  
  1514.         D(("original name |%s|",(*namePtr)));
  1515.         D((" mangled name |%s|",name));
  1516.  
  1517.         /* Look for extra colon characters
  1518.          * embedded in the name (as in "foo:bar:baz"
  1519.          * or "foo/bar:baz") which really don't
  1520.          * belong here.
  1521.          */
  1522.         SHOWMSG("stripping colons");
  1523.         len = strlen(name);
  1524.         for(i = 0 ; i < len ; i++)
  1525.         {
  1526.             if(name[i] == ':' || name[i] == '/')
  1527.             {
  1528.                 int j;
  1529.  
  1530.                 for(j = i+1 ; j < len ; j++)
  1531.                 {
  1532.                     if(name[j] == ':')
  1533.                     {
  1534.                         errno = EINVAL; /* invalid name */
  1535.                         goto out;
  1536.                     }
  1537.                 }
  1538.  
  1539.                 break;
  1540.             }
  1541.         }
  1542.  
  1543.         /* Now check if the file name is longer than the
  1544.          * maximum supported by the ROM file system. This
  1545.          * is to avoid name space clashes.
  1546.          */
  1547.         SHOWMSG("checking file name length");
  1548.         if(strlen(FilePart((STRPTR)name)) > MAX_FFS_NAME_LEN)
  1549.         {
  1550.             LONG error = OK;
  1551.             BPTR fileLock;
  1552.  
  1553.             D(("name is probably too long (%ld > %ld)",strlen(FilePart((STRPTR)name)) > MAX_FFS_NAME_LEN));
  1554.  
  1555.             /* This is a tricky issue: the filing system we are talking
  1556.              * to may be able to handle more than 30 characters, but then
  1557.              * it may be not, it's impossible to tell. We adopt the following
  1558.              * strategy: we try to access the named file and compare its
  1559.              * name against the one reported by the file system. If the name
  1560.              * reported by the file system is shorter than the one provided,
  1561.              * but matches it otherwise, we will assume that trouble is underway
  1562.              * and back out backwards.
  1563.              */
  1564.  
  1565.             ForbidDOS();
  1566.  
  1567.             fileLock = Lock((STRPTR)name,SHARED_LOCK);
  1568.             if(fileLock != ZERO)
  1569.             {
  1570.                 D_S(struct FileInfoBlock,fib);
  1571.  
  1572.                 if(Examine(fileLock,fib))
  1573.                 {
  1574.                     STRPTR file_name = FilePart((STRPTR)name);
  1575.                     int len;
  1576.  
  1577.                     /* Now check if the name reported by the
  1578.                      * filing system is shorter than the
  1579.                      * one we asked for, but matches otherwise.
  1580.                      */
  1581.                     len = strlen(fib->fib_FileName);
  1582.                     if(strlen(file_name) > len && Strnicmp(file_name,fib->fib_FileName,len) == SAME)
  1583.                     {
  1584.                         /* The name is too long to handle. */
  1585.                         error = ERROR_LINE_TOO_LONG;
  1586.                     }
  1587.                 }
  1588.                 else
  1589.                 {
  1590.                     error = IoErr();
  1591.                 }
  1592.  
  1593.                 UnLock(fileLock);
  1594.             }
  1595.             else
  1596.             {
  1597.                 error = IoErr();
  1598.             }
  1599.  
  1600.             PermitDOS();
  1601.  
  1602.             /* We don't complain if the file does
  1603.              * not exist, but if it is currently in
  1604.              * use, on a volume that's not currently
  1605.              * mounted, etc. we will complain.
  1606.              */
  1607.             if(error != OK && error != ERROR_OBJECT_NOT_FOUND)
  1608.             {
  1609.                 SetIoErr(error);
  1610.                 MapIoErrToErrno();
  1611.  
  1612.                 goto out;
  1613.             }
  1614.         }
  1615.  
  1616.         mi->mi_OldName = (*namePtr);
  1617.         (*namePtr) = name;
  1618.  
  1619.         result = OK;
  1620.     }
  1621.  
  1622. out:
  1623.  
  1624.     RETURN(result);
  1625.     return(result);
  1626. }
  1627.  
  1628. /******************************************************************************/
  1629.  
  1630. STATIC int MaxOpenDescriptor = -1;
  1631.  
  1632. STATIC VOID
  1633. CloseUnlinkUnlockCleanup(VOID)
  1634. {
  1635.     struct UFB * ufb;
  1636.     int fd;
  1637.  
  1638.     ForbidDOS();
  1639.  
  1640.     /* Don't let anybody stop us. */
  1641.     signal(SIGINT,SIG_IGN);
  1642.     signal(SIGTERM,SIG_IGN);
  1643.  
  1644.     /* We look for descriptors we marked for
  1645.      * deletion.
  1646.      */
  1647.     for(fd = 0 ; fd <= MaxOpenDescriptor ; fd++)
  1648.     {
  1649.         CleanupFileLocks(fd);
  1650.  
  1651.         ufb = chkufb(fd);
  1652.         if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_UNLINK))
  1653.         {
  1654.             char fileName[MAX_FILENAME_LEN];
  1655.             BOOL removeIt;
  1656.  
  1657.             removeIt = NameFromFH((BPTR)ufb->ufbfh,fileName,sizeof(fileName));
  1658.  
  1659.             CLEAR_FLAG(ufb->ufbflg,UFB_UNLINK);
  1660.  
  1661.             close(fd);
  1662.  
  1663.             if(removeIt)
  1664.                 DeleteFile(fileName);
  1665.         }
  1666.     }
  1667.  
  1668.     PermitDOS();
  1669. }
  1670.  
  1671. int
  1672. amiga_unlink(char *name)
  1673. {
  1674.     struct MangleInfo mi;
  1675.     BPTR fileLock;
  1676.     int result = ERROR;
  1677.  
  1678.     chkabort();
  1679.  
  1680.     ASSERT(name != NULL);
  1681.  
  1682.     ENTER();
  1683.     SHOWSTRING(name);
  1684.  
  1685.     if(MangleName(&name,&mi) == OK)
  1686.     {
  1687.         LONG error = OK;
  1688.  
  1689.         ForbidDOS();
  1690.  
  1691.         fileLock = Lock(name,SHARED_LOCK);
  1692.         if(fileLock != ZERO)
  1693.         {
  1694.             D_S(struct FileInfoBlock,fib);
  1695.  
  1696.             if(Examine(fileLock,fib))
  1697.             {
  1698.                 UnLock(fileLock);
  1699.                 fileLock = ZERO;
  1700.  
  1701.                 /* Make sure that we get to remove
  1702.                  * a file, as the name implies.
  1703.                  */
  1704.                 if(FIB_IS_FILE(fib))
  1705.                 {
  1706.                     if(DeleteFile(name))
  1707.                         result = OK;
  1708.                     else
  1709.                         error = IoErr();
  1710.                 }
  1711.                 else
  1712.                 {
  1713.                     errno = EISDIR;
  1714.                 }
  1715.             }
  1716.             else
  1717.             {
  1718.                 error = IoErr();
  1719.             }
  1720.  
  1721.             UnLock(fileLock);
  1722.         }
  1723.         else
  1724.         {
  1725.             error = IoErr();
  1726.         }
  1727.  
  1728.         PermitDOS();
  1729.  
  1730.         /* Check if we couldn't delete the file in
  1731.          * question because there still is a file
  1732.          * handle attached to it. If we can find that
  1733.          * file, we will mark it for deletion lateron
  1734.          * when the file is closed.
  1735.          */
  1736.         if(result != OK && error == ERROR_OBJECT_IN_USE)
  1737.         {
  1738.             char parentDirName[MAX_FILENAME_LEN];
  1739.             BOOL foundParentDirName;
  1740.             BPTR fileParentDir;
  1741.             int i;
  1742.  
  1743.             ASSERT(strlen(name) < sizeof(parentDirName));
  1744.  
  1745.             strcpy(parentDirName,name);
  1746.             foundParentDirName = FALSE;
  1747.  
  1748.             for(i = ((int)strlen(parentDirName))-1 ; i >= 0 ; i--)
  1749.             {
  1750.                 if(parentDirName[i] == ':')
  1751.                 {
  1752.                     if(parentDirName[i+1] != '\0')
  1753.                     {
  1754.                         parentDirName[i+1] = '\0';
  1755.                         foundParentDirName = TRUE;
  1756.                     }
  1757.  
  1758.                     break;
  1759.                 }
  1760.                 else if (parentDirName[i] == '/')
  1761.                 {
  1762.                     parentDirName[i] = '\0';
  1763.                     foundParentDirName = TRUE;
  1764.                     break;
  1765.                 }
  1766.             }
  1767.  
  1768.             /* Did we find this file's parent directory name? */
  1769.             if(foundParentDirName)
  1770.             {
  1771.                 D(("locking |%s|",parentDirName));
  1772.  
  1773.                 /* Get a lock on the file's parent directory. */
  1774.                 fileParentDir = Lock(parentDirName,SHARED_LOCK);
  1775.                 if(fileParentDir != ZERO)
  1776.                 {
  1777.                     BPTR descriptorParentDir;
  1778.                     BOOL gotIt = FALSE;
  1779.                     struct UFB * ufb;
  1780.                     int fd;
  1781.  
  1782.                     for(fd = 0 ; fd <= MaxOpenDescriptor ; fd++)
  1783.                     {
  1784.                         ufb = chkufb(fd);
  1785.                         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  1786.                         {
  1787.                             /* And also get a lock on the file
  1788.                              * descriptor's parent directory.
  1789.                              */
  1790.                             descriptorParentDir = ParentOfFH((BPTR)ufb->ufbfh);
  1791.                             if(descriptorParentDir != ZERO)
  1792.                             {
  1793.                                 /* Are the two pointing to the same drawer? */
  1794.                                 if(SameLock(fileParentDir,descriptorParentDir) == LOCK_SAME)
  1795.                                 {
  1796.                                     D_S(struct FileInfoBlock,fib);
  1797.  
  1798.                                     if(ExamineFH((BPTR)ufb->ufbfh,fib))
  1799.                                     {
  1800.                                         /* Check if the two share the same name. */
  1801.                                         if(Stricmp(fib->fib_FileName,FilePart(name)) == SAME)
  1802.                                         {
  1803.                                             /* Mark this file for deletion. */
  1804.                                             SET_FLAG(ufb->ufbflg,UFB_UNLINK);
  1805.  
  1806.                                             gotIt = TRUE;
  1807.                                             error = OK;
  1808.                                             result = OK;
  1809.                                         }
  1810.                                     }
  1811.                                     else
  1812.                                     {
  1813.                                         SHOWMSG("couldn't examine the descriptor");
  1814.                                     }
  1815.                                 }
  1816.                                 else
  1817.                                 {
  1818.                                     SHOWMSG("file and descriptor don't live in the same drawer");
  1819.                                 }
  1820.  
  1821.                                 UnLock(descriptorParentDir);
  1822.                             }
  1823.                             else
  1824.                             {
  1825.                                 SHOWMSG("the descriptor doesn't have a parent directory (huh?!?)");
  1826.                             }
  1827.                         }
  1828.  
  1829.                         if(gotIt)
  1830.                             break;
  1831.                     }
  1832.  
  1833.                     UnLock(fileParentDir);
  1834.                 }
  1835.                 else
  1836.                 {
  1837.                     D(("couldn't get a lock on |%s|",parentDirName));
  1838.                 }
  1839.             }
  1840.             else
  1841.             {
  1842.                 D(("didn't find parent dir name of |%s|",name));
  1843.             }
  1844.         }
  1845.  
  1846.         /* Take care of the AmigaDOS error
  1847.          * code, if there is any.
  1848.          */
  1849.         if(result != OK && error != OK)
  1850.         {
  1851.             SetIoErr(error);
  1852.             MapIoErrToErrno();
  1853.         }
  1854.  
  1855.         UnmangleName(&name,&mi);
  1856.     }
  1857.  
  1858.     RETURN(result);
  1859.     return(result);
  1860. }
  1861.  
  1862. int
  1863. amiga_open(char *name,int mode,int prot)
  1864. {
  1865.     struct MangleInfo mi;
  1866.     int result = ERROR;
  1867.  
  1868.     chkabort();
  1869.  
  1870.     ASSERT(name != NULL);
  1871.  
  1872.     ENTER();
  1873.     SHOWSTRING(name);
  1874.     SHOWVALUE(mode);
  1875.     SHOWVALUE(prot);
  1876.  
  1877.     if(MangleName(&name,&mi) == OK)
  1878.     {
  1879.         /* Clear the "no delay" flag since the SAS/C
  1880.          * runtime library does not support it.
  1881.          */
  1882.         CLEAR_FLAG(mode,O_NONBLOCK);
  1883.  
  1884.         ForbidDOS();
  1885.  
  1886.         result = open(name,mode,prot);
  1887.         if(result != ERROR && MaxOpenDescriptor < result)
  1888.             MaxOpenDescriptor = result;
  1889.  
  1890.         PermitDOS();
  1891.  
  1892.         UnmangleName(&name,&mi);
  1893.     }
  1894.  
  1895.     RETURN(result);
  1896.     return(result);
  1897. }
  1898.  
  1899. /******************************************************************************/
  1900.  
  1901. STATIC char CurrentDirName[MAX_FILENAME_LEN] = "";
  1902.  
  1903. int
  1904. amiga_chdir(char *path)
  1905. {
  1906.     BOOL isAbsolutePath;
  1907.     struct MangleInfo mi;
  1908.     int result = ERROR;
  1909.  
  1910.     chkabort();
  1911.  
  1912.     ASSERT(path != NULL);
  1913.  
  1914.     ENTER();
  1915.     SHOWSTRING(path);
  1916.  
  1917.     /* Is this an absolute path? */
  1918.     isAbsolutePath = (BOOL)(path[0] == '/');
  1919.  
  1920.     if(MangleName(&path,&mi) == OK)
  1921.     {
  1922.         BPTR drawerLock;
  1923.  
  1924.         D(("chdir(\"%s\")",path));
  1925.  
  1926.         ForbidDOS();
  1927.  
  1928.         drawerLock = Lock(path,SHARED_LOCK);
  1929.         if(drawerLock != ZERO)
  1930.         {
  1931.             D_S(struct FileInfoBlock,fib);
  1932.  
  1933.             if(Examine(drawerLock,fib))
  1934.             {
  1935.                 /* We can only move into drawers. */
  1936.                 if(FIB_IS_DRAWER(fib))
  1937.                 {
  1938.                     /* If necessary, get the name of
  1939.                      * the drawer to move into.
  1940.                      */
  1941.                     if(NOT isAbsolutePath)
  1942.                     {
  1943.                         UBYTE localName[MAX_FILENAME_LEN];
  1944.  
  1945.                         if(NameFromLock(drawerLock,localName,sizeof(localName)))
  1946.                             result = MapFileNameAmigaToUnix(localName,CurrentDirName,sizeof(CurrentDirName));
  1947.                         else
  1948.                             MapIoErrToErrno();
  1949.                     }
  1950.                     else
  1951.                     {
  1952.                         result = OK;
  1953.                     }
  1954.  
  1955.                     /* If everything went well,
  1956.                      * move into the drawer.
  1957.                      */
  1958.                     if(result == OK)
  1959.                     {
  1960.                         BPTR oldDrawer;
  1961.  
  1962.                         oldDrawer = CurrentDir(drawerLock);
  1963.  
  1964.                         /* Unlock the old drawer we came from
  1965.                          * unless we want to return to it
  1966.                          * when the program exits.
  1967.                          */
  1968.                         if(InitialCurrentDirInitialized)
  1969.                         {
  1970.                             UnLock(oldDrawer);
  1971.                         }
  1972.                         else
  1973.                         {
  1974.                             InitialCurrentDir = oldDrawer;
  1975.                             InitialCurrentDirInitialized = TRUE;
  1976.                         }
  1977.  
  1978.                         /* Make sure that this drawer is going
  1979.                          * to be unlocked when the program exits.
  1980.                          */
  1981.                         ChangedCurrentDir = drawerLock;
  1982.                     }
  1983.                 }
  1984.                 else
  1985.                 {
  1986.                     errno = ENOTDIR;
  1987.                 }
  1988.             }
  1989.             else
  1990.             {
  1991.                 MapIoErrToErrno();
  1992.             }
  1993.  
  1994.             if(result != OK)
  1995.                 UnLock(drawerLock);
  1996.         }
  1997.         else
  1998.         {
  1999.             MapIoErrToErrno();
  2000.         }
  2001.  
  2002.         PermitDOS();
  2003.  
  2004.         UnmangleName(&path,&mi);
  2005.  
  2006.         if(result == OK && isAbsolutePath)
  2007.             strcpy(CurrentDirName,path);
  2008.     }
  2009.  
  2010.     RETURN(result);
  2011.     return(result);
  2012. }
  2013.  
  2014. /******************************************************************************/
  2015.  
  2016. struct OpenDirNode
  2017. {
  2018.     struct MinNode            odn_MinNode;
  2019.     BPTR                    odn_FileLock;
  2020.     struct FileInfoBlock    odn_FIB;
  2021.     struct List                odn_VolumeList;
  2022.     DIR                        odn_DIR;
  2023.     BOOL                    odn_ReadingVolumes;
  2024.     struct dirent            odn_DirectoryEntry;
  2025.     struct Node *            odn_NextNode;
  2026.     ULONG                    odn_NextDirEntryIndex;
  2027.     LONG                    odn_ParentDirKey;
  2028. };
  2029.  
  2030. STATIC struct List OpenDirList;
  2031. STATIC BOOL OpenDirListInitialized = FALSE;
  2032.  
  2033. STATIC ULONG RootBlocks = 0;
  2034. STATIC ULONG RootBlocksUsed = 0;
  2035.  
  2036. STATIC VOID
  2037. OpenDirCleanup(VOID)
  2038. {
  2039.     struct OpenDirNode * odn;
  2040.  
  2041.     /* Unlock all directories still being scanned
  2042.      * when exit() was called.
  2043.      */
  2044.     for(odn = (struct OpenDirNode *)OpenDirList.lh_Head ;
  2045.         odn->odn_MinNode.mln_Succ != NULL ;
  2046.         odn = (struct OpenDirNode *)odn->odn_MinNode.mln_Succ)
  2047.     {
  2048.         UnLock(odn->odn_FileLock);
  2049.     }
  2050. }
  2051.  
  2052. DIR *
  2053. amiga_opendir(char *dirName)
  2054. {
  2055.     char localDirName[MAX_FILENAME_LEN];
  2056.     struct List volumeList;
  2057.     struct Node * node;
  2058.     DIR *result = NULL;
  2059.  
  2060.     chkabort();
  2061.  
  2062.     ASSERT(dirName != NULL);
  2063.  
  2064.     ENTER();
  2065.  
  2066.     SHOWSTRING(dirName);
  2067.  
  2068.     /* This is for buffering the list of available volumes. */
  2069.     NewList(&volumeList);
  2070.  
  2071.     /* Make sure that the directory list is
  2072.      * set up properly.
  2073.      */
  2074.     if(NOT OpenDirListInitialized)
  2075.     {
  2076.         NewList(&OpenDirList);
  2077.         OpenDirListInitialized = TRUE;
  2078.         atexit(OpenDirCleanup);
  2079.     }
  2080.  
  2081.     if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  2082.     {
  2083.         /* Check if we are to scan the virtual root directory. */
  2084.         if(strcmp(dirName,"/") == SAME)
  2085.         {
  2086.             struct OpenDirNode * odn;
  2087.  
  2088.             odn = malloc(sizeof(*odn));
  2089.             if(odn != NULL)
  2090.             {
  2091.                 struct DosList * dol;
  2092.  
  2093.                 RootBlocks = RootBlocksUsed = 0;
  2094.  
  2095.                 memset(odn,0,sizeof(*odn));
  2096.                 odn->odn_ReadingVolumes = TRUE;
  2097.                 odn->odn_DIR.dd_buf = (char *)odn;
  2098.                 NewList(&odn->odn_VolumeList);
  2099.  
  2100.                 AddHead(&OpenDirList,(struct Node *)odn);
  2101.  
  2102.                 errno = OK;
  2103.  
  2104.                 /* Now collect all volumes in the system. */
  2105.                 dol = NextDosEntry(LockDosList(LDF_VOLUMES|LDF_READ),
  2106.                                                LDF_VOLUMES|LDF_READ);
  2107.                 while(dol != NULL)
  2108.                 {
  2109.                     /* Does the volume refer to a medium that is right
  2110.                      * now present in the drive?
  2111.                      */
  2112.                     if(dol->dol_Task != NULL)
  2113.                     {
  2114.                         STRPTR name;
  2115.  
  2116.                         name = BADDR(dol->dol_Name);
  2117.                         if(name != NULL && name[0] > 0)
  2118.                         {
  2119.                             LONG len;
  2120.  
  2121.                             len = name[0];
  2122.  
  2123.                             node = malloc(sizeof(*node) + len + 2);
  2124.                             if(node != NULL)
  2125.                             {
  2126.                                 node->ln_Name = (char *)(node + 1);
  2127.                                 memcpy(node->ln_Name,name+1,len);
  2128.                                 node->ln_Name[len++] = ':';
  2129.                                 node->ln_Name[len] = '\0';
  2130.  
  2131.                                 AddTail(&volumeList,node);
  2132.                             }
  2133.                             else
  2134.                             {
  2135.                                 errno = ENOMEM;
  2136.                                 break;
  2137.                             }
  2138.                         }
  2139.                     }
  2140.  
  2141.                     dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  2142.                 }
  2143.  
  2144.                 UnLockDosList(LDF_VOLUMES|LDF_READ);
  2145.  
  2146.                 /* If everything went well, proceed to examine every
  2147.                  * volume previously added to the local volume list.
  2148.                  * This procedure is necessary to avoid sending
  2149.                  * packets to file systems while the DosList is
  2150.                  * locked, which is a big NO-NO.
  2151.                  */
  2152.                 if(errno == OK)
  2153.                 {
  2154.                     D_S(struct InfoData,id);
  2155.                     struct MsgPort * task;
  2156.  
  2157.                     result = &odn->odn_DIR;
  2158.  
  2159.                     while((node = RemHead(&volumeList)) != NULL)
  2160.                     {
  2161.                         task = DeviceProc(node->ln_Name);
  2162.                         if(task != NULL)
  2163.                         {
  2164.                             /* Is there a disk present? */
  2165.                             if(DoPkt(task,ACTION_DISK_INFO,MKBADDR(id),    0,0,0,0))
  2166.                             {
  2167.                                 /* Collect the number of blocks used and
  2168.                                  * available in our fake root directory.
  2169.                                  * Not that it matters much...
  2170.                                  */
  2171.                                 if(id->id_BytesPerBlock == 512)
  2172.                                 {
  2173.                                     RootBlocks        += id->id_NumBlocks;
  2174.                                     RootBlocksUsed    += id->id_NumBlocksUsed;
  2175.                                 }
  2176.                                 else
  2177.                                 {
  2178.                                     RootBlocks        += (id->id_NumBlocks * id->id_BytesPerBlock) / 512;
  2179.                                     RootBlocksUsed    += (id->id_NumBlocksUsed * id->id_BytesPerBlock) / 512;
  2180.                                 }
  2181.  
  2182.                                 /* Remove the trailing colon character. */
  2183.                                 node->ln_Name[strlen(node->ln_Name)-1] = '\0';
  2184.  
  2185.                                 AddTail(&odn->odn_VolumeList,node);
  2186.  
  2187.                                 if(odn->odn_NextNode == NULL)
  2188.                                     odn->odn_NextNode = node;
  2189.  
  2190.                                 node = NULL;
  2191.                             }
  2192.                         }
  2193.  
  2194.                         if(node != NULL)
  2195.                             free(node);
  2196.                     }
  2197.                 }
  2198.             }
  2199.             else
  2200.             {
  2201.                 errno = ENOMEM;
  2202.             }
  2203.         }
  2204.         else
  2205.         {
  2206.             struct MangleInfo mi;
  2207.  
  2208.             if(MangleName(&dirName,&mi) == OK)
  2209.             {
  2210.                 BPTR fileLock;
  2211.  
  2212.                 ForbidDOS();
  2213.  
  2214.                 fileLock = Lock(dirName,SHARED_LOCK);
  2215.                 if(fileLock != ZERO)
  2216.                 {
  2217.                     struct OpenDirNode * odn;
  2218.  
  2219.                     odn = malloc(sizeof(*odn));
  2220.                     if(odn != NULL)
  2221.                     {
  2222.                         BPTR parentDir;
  2223.  
  2224.                         memset(odn,0,sizeof(*odn));
  2225.  
  2226.                         parentDir = ParentDir(fileLock);
  2227.                         if(parentDir != ZERO)
  2228.                         {
  2229.                             if(Examine(parentDir,&odn->odn_FIB))
  2230.                                 odn->odn_ParentDirKey = odn->odn_FIB.fib_DiskKey;
  2231.  
  2232.                             UnLock(parentDir);
  2233.                         }
  2234.  
  2235.                         if(Examine(fileLock,&odn->odn_FIB))
  2236.                         {
  2237.                             /* Make sure that we are
  2238.                              * trying to read a drawer
  2239.                              * and not a file.
  2240.                              */
  2241.                             if(FIB_IS_DRAWER(&odn->odn_FIB))
  2242.                             {
  2243.                                 odn->odn_DIR.dd_buf = (char *)odn;
  2244.                                 odn->odn_FileLock = fileLock;
  2245.                                 NewList(&odn->odn_VolumeList);
  2246.  
  2247.                                 /* The lock has been "swallowed"
  2248.                                  * by the dir node; make sure that
  2249.                                  * we don't unlock it.
  2250.                                  */
  2251.                                 fileLock = ZERO;
  2252.  
  2253.                                 AddHead(&OpenDirList,(struct Node *)odn);
  2254.                                 result = &odn->odn_DIR;
  2255.                             }
  2256.                             else
  2257.                             {
  2258.                                 errno = ENOTDIR;
  2259.                             }
  2260.                         }
  2261.                         else
  2262.                         {
  2263.                             MapIoErrToErrno();
  2264.                         }
  2265.  
  2266.                         if(result == NULL)
  2267.                             free(odn);
  2268.                     }
  2269.                     else
  2270.                     {
  2271.                         errno = ENOMEM;
  2272.                     }
  2273.  
  2274.                     UnLock(fileLock);
  2275.                 }
  2276.                 else
  2277.                 {
  2278.                     MapIoErrToErrno();
  2279.                 }
  2280.  
  2281.                 PermitDOS();
  2282.  
  2283.                 UnmangleName(&dirName,&mi);
  2284.             }
  2285.         }
  2286.     }
  2287.  
  2288.     /* Get rid of any leftovers. */
  2289.     while((node = RemHead(&volumeList)) != NULL)
  2290.         free(node);
  2291.  
  2292.     RETURN(result);
  2293.     return(result);
  2294. }
  2295.  
  2296. VOID
  2297. amiga_closedir(DIR *dir)
  2298. {
  2299.     ENTER();
  2300.  
  2301.     if(dir != NULL)
  2302.     {
  2303.         struct OpenDirNode * odn;
  2304.  
  2305.         odn = (struct OpenDirNode *)dir->dd_buf;
  2306.         if(odn != NULL)
  2307.         {
  2308.             struct Node * node;
  2309.  
  2310.             Remove((struct Node *)odn);
  2311.  
  2312.             while((node = RemHead(&odn->odn_VolumeList)) != NULL)
  2313.                 free(node);
  2314.  
  2315.             UnLock(odn->odn_FileLock);
  2316.             free(odn);
  2317.         }
  2318.     }
  2319.  
  2320.     chkabort();
  2321.  
  2322.     LEAVE();
  2323. }
  2324.  
  2325. struct dirent *
  2326. amiga_readdir(DIR *dir)
  2327. {
  2328.     struct dirent * result = NULL;
  2329.  
  2330.     ENTER();
  2331.  
  2332.     chkabort();
  2333.  
  2334.     if(dir != NULL)
  2335.     {
  2336.         struct OpenDirNode * odn;
  2337.  
  2338.         odn = (struct OpenDirNode *)dir->dd_buf;
  2339.         if(odn != NULL)
  2340.         {
  2341.             struct dirent * d = &odn->odn_DirectoryEntry;
  2342.  
  2343.             if(odn->odn_ReadingVolumes)
  2344.             {
  2345.                 SHOWMSG("we are reading the virtual root directory");
  2346.  
  2347.                 /* The first directory entry points
  2348.                  * back to the directory itself.
  2349.                  */
  2350.                 if(odn->odn_NextDirEntryIndex == 0)
  2351.                 {
  2352.                     SHOWMSG("this is the first read attempt; returning the dot.");
  2353.  
  2354.                     strcpy(d->d_name,".");
  2355.  
  2356.                     d->d_ino    = ++odn->odn_NextDirEntryIndex;
  2357.                     d->d_namlen    = strlen(d->d_name);
  2358.  
  2359.                     result = d;
  2360.                 }
  2361.                 else
  2362.                 {
  2363.                     /* Return the next volume in the list. */
  2364.                     if(odn->odn_NextNode != NULL && odn->odn_NextNode->ln_Succ != NULL)
  2365.                     {
  2366.                         ASSERT(sizeof(d->d_name) >= strlen(odn->odn_NextNode->ln_Name));
  2367.  
  2368.                         SHOWMSG("returning the next volume");
  2369.  
  2370.                         strcpy(d->d_name,odn->odn_NextNode->ln_Name);
  2371.  
  2372.                         odn->odn_NextNode = odn->odn_NextNode->ln_Succ;
  2373.  
  2374.                         d->d_ino    = odn->odn_NextDirEntryIndex++;
  2375.                         d->d_namlen    = strlen(d->d_name);
  2376.  
  2377.                         result = d;
  2378.                     }
  2379.                     else
  2380.                     {
  2381.                         errno = 0;
  2382.                     }
  2383.                 }
  2384.             }
  2385.             else
  2386.             {
  2387.                 SHOWMSG("we are reading a user directory");
  2388.  
  2389.                 if(odn->odn_NextDirEntryIndex == 0)
  2390.                 {
  2391.                     SHOWMSG("returning '.'");
  2392.  
  2393.                     /* The first directory entry points
  2394.                      * back to the directory itself.
  2395.                      */
  2396.                     strcpy(d->d_name,".");
  2397.  
  2398.                     d->d_ino    = odn->odn_FIB.fib_DiskKey;
  2399.                     d->d_namlen    = strlen(d->d_name);
  2400.  
  2401.                     odn->odn_NextDirEntryIndex++;
  2402.                     result = d;
  2403.                 }
  2404.                 else if(odn->odn_NextDirEntryIndex == 1)
  2405.                 {
  2406.                     SHOWMSG("returning '..'");
  2407.  
  2408.                     /* The second directory entry points
  2409.                      * to the parent directory.
  2410.                      */
  2411.                     strcpy(d->d_name,"..");
  2412.  
  2413.                     d->d_ino    = odn->odn_ParentDirKey;
  2414.                     d->d_namlen    = strlen(d->d_name);
  2415.  
  2416.                     odn->odn_NextDirEntryIndex++;
  2417.                     result = d;
  2418.                 }
  2419.                 else
  2420.                 {
  2421.                     SHOWMSG("returning next directory entry");
  2422.  
  2423.                     ForbidDOS();
  2424.  
  2425.                     /* All other iterations pick up the
  2426.                      * next following directory entry.
  2427.                      */
  2428.                     if(ExNext(odn->odn_FileLock,&odn->odn_FIB))
  2429.                     {
  2430.                         ASSERT(sizeof(d->d_name) >= strlen(odn->odn_FIB.fib_FileName));
  2431.                         SHOWMSG("got another entry");
  2432.  
  2433.                         strcpy(d->d_name,odn->odn_FIB.fib_FileName);
  2434.  
  2435.                         d->d_ino    = odn->odn_FIB.fib_DiskKey;
  2436.                         d->d_namlen    = strlen(d->d_name);
  2437.  
  2438.                         result = d;
  2439.                     }
  2440.                     else
  2441.                     {
  2442.                         LONG error = IoErr();
  2443.  
  2444.                         if(error == ERROR_NO_MORE_ENTRIES)
  2445.                         {
  2446.                             SHOWMSG("there is no next directory entry.");
  2447.                             errno = 0;
  2448.                         }
  2449.                         else
  2450.                         {
  2451.                             SHOWMSG("some other problem...");
  2452.  
  2453.                             SetIoErr(error);
  2454.                             MapIoErrToErrno();
  2455.                         }
  2456.                     }
  2457.  
  2458.                     PermitDOS();
  2459.                 }
  2460.             }
  2461.         }
  2462.     }
  2463.  
  2464.     if(result != NULL)
  2465.         SHOWSTRING(result->d_name);
  2466.  
  2467.     RETURN(result);
  2468.     return(result);
  2469. }
  2470.  
  2471. /******************************************************************************/
  2472.  
  2473. STATIC int
  2474. TranslateRelativePath(char **namePtr,char *replace,int maxReplaceLen)
  2475. {
  2476.     int result = ERROR;
  2477.     char * name;
  2478.  
  2479.     ENTER();
  2480.  
  2481.     ASSERT(namePtr != NULL && (*namePtr) != NULL && replace != NULL);
  2482.  
  2483.     /* If we have a current directory all references should
  2484.      * be made relative to, do just that. Absolute paths
  2485.      * are not modified, though.
  2486.      */
  2487.     name = (*namePtr);
  2488.     if(NOT STRING_IS_EMPTY(CurrentDirName) && name[0] != '/')
  2489.     {
  2490.         int totalLen;
  2491.  
  2492.         SHOWMSG("Changing the directory name");
  2493.  
  2494.         /* Skip current dir modifiers, we just want the name. */
  2495.         if(strncmp(name,"./",2) == SAME)
  2496.             name += 2;
  2497.         else if (strcmp(name,".") == SAME)
  2498.             name = "";
  2499.  
  2500.         /* Get the current directory name and get
  2501.          * ready to attach the file name at the end.
  2502.          */
  2503.         totalLen = strlen(CurrentDirName);
  2504.  
  2505.         if(CurrentDirName[totalLen-1] != '/' &&
  2506.            CurrentDirName[totalLen-1] != ':' &&
  2507.            NOT STRING_IS_EMPTY(name))
  2508.         {
  2509.             totalLen++;
  2510.         }
  2511.  
  2512.         totalLen += strlen(name);
  2513.  
  2514.         /* Check if the complete string will fit. */
  2515.         if(totalLen < maxReplaceLen)
  2516.         {
  2517.             /* Put the file name together. */
  2518.             strcpy(replace,CurrentDirName);
  2519.             if(CurrentDirName[strlen(CurrentDirName)-1] != '/' && NOT STRING_IS_EMPTY(name))
  2520.                 strcat(replace,"/");
  2521.  
  2522.             strcat(replace,name);
  2523.  
  2524.             (*namePtr) = replace;
  2525.             SHOWSTRING(*namePtr);
  2526.  
  2527.             result = OK;
  2528.         }
  2529.         else
  2530.         {
  2531.             errno = ENAMETOOLONG;
  2532.         }
  2533.     }
  2534.     else
  2535.     {
  2536.         result = OK;
  2537.     }
  2538.  
  2539.     RETURN(result);
  2540.     return(result);
  2541. }
  2542.  
  2543. /******************************************************************************/
  2544.  
  2545. int
  2546. amiga_mkdir(char *name,int mode)
  2547. {
  2548.     struct MangleInfo mi;
  2549.     BPTR dirLock;
  2550.     int result = ERROR;
  2551.  
  2552.     chkabort();
  2553.  
  2554.     ASSERT(name != NULL);
  2555.  
  2556.     ENTER();
  2557.     SHOWSTRING(name);
  2558.     SHOWVALUE(mode);
  2559.  
  2560.     if(MangleName(&name,&mi) == OK)
  2561.     {
  2562.         ForbidDOS();
  2563.  
  2564.         dirLock = CreateDir((STRPTR)name);
  2565.         if(dirLock != ZERO)
  2566.         {
  2567.             UnLock(dirLock);
  2568.             result = OK;
  2569.         }
  2570.         else
  2571.         {
  2572.             MapIoErrToErrno();
  2573.         }
  2574.  
  2575.         PermitDOS();
  2576.  
  2577.         UnmangleName(&name,&mi);
  2578.     }
  2579.  
  2580.     if(result == OK)
  2581.         result = amiga_chmod(name,mode);
  2582.  
  2583.     RETURN(result);
  2584.     return(result);
  2585. }
  2586.  
  2587. /******************************************************************************/
  2588.  
  2589. int
  2590. amiga_rmdir(char *name)
  2591. {
  2592.     struct MangleInfo mi;
  2593.     BPTR fileLock;
  2594.     int result = ERROR;
  2595.  
  2596.     chkabort();
  2597.  
  2598.     ENTER();
  2599.     SHOWSTRING(name);
  2600.  
  2601.     if(MangleName(&name,&mi) == OK)
  2602.     {
  2603.         ForbidDOS();
  2604.  
  2605.         fileLock = Lock(name,SHARED_LOCK);
  2606.         if(fileLock != ZERO)
  2607.         {
  2608.             D_S(struct FileInfoBlock,fib);
  2609.  
  2610.             if(Examine(fileLock,fib))
  2611.             {
  2612.                 UnLock(fileLock);
  2613.                 fileLock = ZERO;
  2614.  
  2615.                 /* Make sure that we get to remove a drawer,
  2616.                  * as the function name implies.
  2617.                  */
  2618.                 if(FIB_IS_DRAWER(fib))
  2619.                 {
  2620.                     if(DeleteFile(name))
  2621.                         result = OK;
  2622.                     else
  2623.                         MapIoErrToErrno();
  2624.                 }
  2625.                 else
  2626.                 {
  2627.                     errno = ENOTDIR;
  2628.                 }
  2629.             }
  2630.             else
  2631.             {
  2632.                 MapIoErrToErrno();
  2633.             }
  2634.  
  2635.             UnLock(fileLock);
  2636.         }
  2637.         else
  2638.         {
  2639.             MapIoErrToErrno();
  2640.         }
  2641.  
  2642.         PermitDOS();
  2643.  
  2644.         UnmangleName(&name,&mi);
  2645.     }
  2646.  
  2647.     RETURN(result);
  2648.     return(result);
  2649. }
  2650.  
  2651. /******************************************************************************/
  2652.  
  2653. int
  2654. amiga_creat(char *name,int prot)
  2655. {
  2656.     struct MangleInfo mi;
  2657.     int result = ERROR;
  2658.  
  2659.     chkabort();
  2660.  
  2661.     ASSERT(name != NULL);
  2662.  
  2663.     ENTER();
  2664.     SHOWSTRING(name);
  2665.     SHOWVALUE(prot);
  2666.  
  2667.     if(MangleName(&name,&mi) == OK)
  2668.     {
  2669.         ForbidDOS();
  2670.         result = creat(name,prot);
  2671.         PermitDOS();
  2672.  
  2673.         UnmangleName(&name,&mi);
  2674.     }
  2675.  
  2676.     RETURN(result);
  2677.     return(result);
  2678. }
  2679.  
  2680. /******************************************************************************/
  2681.  
  2682. FILE *
  2683. amiga_fopen(char *name,char *mode)
  2684. {
  2685.     struct MangleInfo mi;
  2686.     FILE *result = NULL;
  2687.  
  2688.     chkabort();
  2689.  
  2690.     ASSERT(name != NULL && mode != NULL);
  2691.  
  2692.     ENTER();
  2693.     SHOWSTRING(name);
  2694.     SHOWSTRING(mode);
  2695.  
  2696.     if(MangleName(&name,&mi) == OK)
  2697.     {
  2698.         ForbidDOS();
  2699.         result = fopen(name,mode);
  2700.         PermitDOS();
  2701.  
  2702.         UnmangleName(&name,&mi);
  2703.     }
  2704.  
  2705.     RETURN(result);
  2706.     return(result);
  2707. }
  2708.  
  2709. /******************************************************************************/
  2710.  
  2711. int
  2712. amiga_rename(char *old,char *new)
  2713. {
  2714.     struct MangleInfo old_mi;
  2715.     struct MangleInfo new_mi;
  2716.     int result = ERROR;
  2717.  
  2718.     chkabort();
  2719.  
  2720.     ASSERT(old != NULL && new != NULL);
  2721.  
  2722.     ENTER();
  2723.     SHOWSTRING(old);
  2724.     SHOWSTRING(new);
  2725.  
  2726.     /* rename() causes the link named <from> to be renamed as <to>. If <to> exists,
  2727.      * it is first removed. Both <from> and <to> must be of the same type (that is,
  2728.      * both directories or both non-directories), and must reside on the same
  2729.      * file system.
  2730.      */
  2731.  
  2732.     if(MangleName(&old,&old_mi) == OK)
  2733.     {
  2734.         if(MangleName(&new,&new_mi) == OK)
  2735.         {
  2736.             ForbidDOS();
  2737.  
  2738.             D(("rename |%s| to |%s|",old,new));
  2739.  
  2740.             if(CANNOT Rename(old,new))
  2741.             {
  2742.                 LONG error = IoErr();
  2743.  
  2744.                 SHOWVALUE(error);
  2745.  
  2746.                 if(error == ERROR_OBJECT_EXISTS)
  2747.                 {
  2748.                     BPTR oldLock = Lock(old,SHARED_LOCK);
  2749.                     BPTR newLock = Lock(new,SHARED_LOCK);
  2750.  
  2751.                     if(oldLock != ZERO && newLock != ZERO && SameLock(oldLock,newLock) == LOCK_SAME)
  2752.                     {
  2753.                         result = OK;
  2754.                         error = OK;
  2755.  
  2756.                         SHOWMSG("Ok; same name");
  2757.  
  2758.                         UnLock(oldLock);
  2759.                         UnLock(newLock);
  2760.                     }
  2761.                     else
  2762.                     {
  2763.                         UnLock(oldLock);
  2764.                         UnLock(newLock);
  2765.  
  2766.                         if(DeleteFile(new))
  2767.                         {
  2768.                             if(Rename(old,new))
  2769.                             {
  2770.                                 result = OK;
  2771.                                 error = OK;
  2772.  
  2773.                                 SHOWMSG("Ok; after removing");
  2774.                             }
  2775.                             else
  2776.                             {
  2777.                                 error = IoErr();
  2778.                             }
  2779.                         }
  2780.                         else
  2781.                         {
  2782.                             error = IoErr();
  2783.                         }
  2784.                     }
  2785.                 }
  2786.  
  2787.                 if(error != OK)
  2788.                 {
  2789.                     SHOWVALUE(error);
  2790.  
  2791.                     SetIoErr(error);
  2792.                     MapIoErrToErrno();
  2793.                 }
  2794.             }
  2795.             else
  2796.             {
  2797.                 SHOWMSG("Ok");
  2798.  
  2799.                 result = OK;
  2800.             }
  2801.  
  2802.             PermitDOS();
  2803.  
  2804.             UnmangleName(&new,&new_mi);
  2805.         }
  2806.         else
  2807.         {
  2808.             SHOWMSG("MangleName new_mi failed");
  2809.         }
  2810.  
  2811.         UnmangleName(&old,&old_mi);
  2812.     }
  2813.     else
  2814.     {
  2815.         SHOWMSG("MangleName old_mi failed");
  2816.     }
  2817.  
  2818.     RETURN(result);
  2819.     return(result);
  2820. }
  2821.  
  2822. /******************************************************************************/
  2823.  
  2824. char *
  2825. amiga_getcwd(char *buf, size_t size)
  2826. {
  2827.     char *result = NULL;
  2828.  
  2829.     chkabort();
  2830.  
  2831.     ASSERT(buf != NULL);
  2832.  
  2833.     ENTER();
  2834.     SHOWVALUE(buf);
  2835.     SHOWVALUE(size);
  2836.  
  2837.     if(CurrentDirName[0] == '/')
  2838.     {
  2839.         strncpy(buf,CurrentDirName,size-1);
  2840.         buf[size-1] = '\0';
  2841.         result = buf;
  2842.     }
  2843.     else
  2844.     {
  2845.         BPTR oldDir;
  2846.  
  2847.         ForbidDOS();
  2848.  
  2849.         oldDir = CurrentDir(ZERO);
  2850.  
  2851.         if(NameFromLock(oldDir,buf,size))
  2852.         {
  2853.             if(MapFileNameAmigaToUnix(buf,buf,size) == OK)
  2854.                 result = buf;
  2855.         }
  2856.         else
  2857.         {
  2858.             MapIoErrToErrno();
  2859.         }
  2860.  
  2861.         CurrentDir(oldDir);
  2862.  
  2863.         PermitDOS();
  2864.     }
  2865.  
  2866.     SHOWSTRING(result);
  2867.  
  2868.     RETURN(result);
  2869.     return(result);
  2870. }
  2871.  
  2872. /******************************************************************************/
  2873.  
  2874. #define SET_FILESIZE_ERROR (-1)
  2875.  
  2876. int
  2877. amiga_ftruncate(int fd,off_t size)
  2878. {
  2879.     struct UFB * ufb;
  2880.     int result = ERROR;
  2881.  
  2882.     chkabort();
  2883.  
  2884.     ENTER();
  2885.     SHOWVALUE(fd);
  2886.     SHOWVALUE(size);
  2887.  
  2888.     ufb = chkufb(fd);
  2889.     if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  2890.     {
  2891.         ForbidDOS();
  2892.  
  2893.         if(SetFileSize((BPTR)ufb->ufbfh,size,OFFSET_BEGINNING) != SET_FILESIZE_ERROR)
  2894.             result = OK;
  2895.         else
  2896.             MapIoErrToErrno();
  2897.  
  2898.         PermitDOS();
  2899.     }
  2900.     else
  2901.     {
  2902.         errno = EBADF;
  2903.     }
  2904.  
  2905.     RETURN(result);
  2906.     return(result);
  2907. }
  2908.  
  2909. /******************************************************************************/
  2910.  
  2911. int
  2912. amiga_accept(int sockfd,struct sockaddr *cliaddr,int *addrlen)
  2913. {
  2914.     struct UFB * ufb;
  2915.     int result = ERROR;
  2916.  
  2917.     chkabort();
  2918.  
  2919.     ASSERT(cliaddr != NULL && addrlen != NULL);
  2920.  
  2921.     ENTER();
  2922.     SHOWVALUE(sockfd);
  2923.     SHOWVALUE(cliaddr);
  2924.     SHOWVALUE(addrlen);
  2925.  
  2926.     ufb = chkufb(sockfd);
  2927.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2928.         result = accept(ufb->ufbfh,cliaddr,(LONG *)addrlen);
  2929.     else
  2930.         errno = ENOTSOCK;
  2931.  
  2932.     RETURN(result);
  2933.     return(result);
  2934. }
  2935.  
  2936. /******************************************************************************/
  2937.  
  2938. int
  2939. amiga_bind(int sockfd,struct sockaddr *name,int namelen)
  2940. {
  2941.     struct UFB * ufb;
  2942.     int result = ERROR;
  2943.  
  2944.     chkabort();
  2945.  
  2946.     ASSERT(name != NULL);
  2947.  
  2948.     ENTER();
  2949.     SHOWVALUE(sockfd);
  2950.     SHOWVALUE(name);
  2951.     SHOWVALUE(namelen);
  2952.  
  2953.     ufb = chkufb(sockfd);
  2954.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2955.         result = bind(ufb->ufbfh,name,namelen);
  2956.     else
  2957.         errno = ENOTSOCK;
  2958.  
  2959.     RETURN(result);
  2960.     return(result);
  2961. }
  2962.  
  2963. /******************************************************************************/
  2964.  
  2965. int
  2966. amiga_close(int fd)
  2967. {
  2968.     struct UFB * ufb;
  2969.     int result = ERROR;
  2970.  
  2971.     chkabort();
  2972.  
  2973.     ENTER();
  2974.     SHOWVALUE(fd);
  2975.  
  2976.     ufb = chkufb(fd);
  2977.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2978.     {
  2979.         result = CloseSocket(ufb->ufbfh);
  2980.         CLEAR_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  2981.  
  2982.         /* Make sure that the descriptor looks like a file again. */
  2983.         RestoreDescriptor(ufb);
  2984.  
  2985.         close(fd);
  2986.     }
  2987.     else
  2988.     {
  2989.         if(ufb != NULL)
  2990.         {
  2991.             /* Don't close the stdio streams! */
  2992.             if(fd == 0 || fd == 1 || fd == 2)
  2993.             {
  2994.                 D(("Attempt to muck with fd #%ld!",fd));
  2995.  
  2996.                 errno = EBADF;
  2997.             }
  2998.             else
  2999.             {
  3000.                 char fileName[MAX_FILENAME_LEN];
  3001.                 BOOL removeIt = FALSE;
  3002.  
  3003.                 if(FLAG_IS_SET(ufb->ufbflg,UFB_UNLINK))
  3004.                 {
  3005.                     removeIt = NameFromFH((BPTR)ufb->ufbfh,fileName,sizeof(fileName));
  3006.  
  3007.                     CLEAR_FLAG(ufb->ufbflg,UFB_UNLINK);
  3008.                 }
  3009.  
  3010.                 CleanupFileLocks(fd);
  3011.  
  3012.                 result = close(fd);
  3013.  
  3014.                 if(removeIt)
  3015.                     DeleteFile(fileName);
  3016.             }
  3017.         }
  3018.         else
  3019.         {
  3020.             errno = EBADF;
  3021.         }
  3022.     }
  3023.  
  3024.     RETURN(result);
  3025.     return(result);
  3026. }
  3027.  
  3028. /******************************************************************************/
  3029.  
  3030. int
  3031. amiga_connect(int sockfd,struct sockaddr *name,int namelen)
  3032. {
  3033.     struct UFB * ufb;
  3034.     int result = ERROR;
  3035.  
  3036.     chkabort();
  3037.  
  3038.     ASSERT(name != NULL && namelen > 0);
  3039.  
  3040.     ENTER();
  3041.     SHOWVALUE(sockfd);
  3042.     SHOWVALUE(name);
  3043.     SHOWVALUE(namelen);
  3044.  
  3045.     ufb = chkufb(sockfd);
  3046.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3047.         result = connect(ufb->ufbfh,name,namelen);
  3048.     else
  3049.         errno = ENOTSOCK;
  3050.  
  3051.     RETURN(result);
  3052.     return(result);
  3053. }
  3054.  
  3055. /******************************************************************************/
  3056.  
  3057. int
  3058. amiga_getpeername(int sockfd,struct sockaddr *name,int *namelen)
  3059. {
  3060.     struct UFB * ufb;
  3061.     int result = ERROR;
  3062.  
  3063.     chkabort();
  3064.  
  3065.     ASSERT(name != NULL && namelen != NULL);
  3066.  
  3067.     ENTER();
  3068.     SHOWVALUE(sockfd);
  3069.     SHOWVALUE(name);
  3070.     SHOWVALUE(namelen);
  3071.  
  3072.     ufb = chkufb(sockfd);
  3073.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3074.         result = getpeername(ufb->ufbfh,name,(LONG *)namelen);
  3075.     else
  3076.         errno = ENOTSOCK;
  3077.  
  3078.     RETURN(result);
  3079.     return(result);
  3080. }
  3081.  
  3082. /******************************************************************************/
  3083.  
  3084. int
  3085. amiga_getsockopt(int sockfd,int level,int optname,VOID *optval,int *optlen)
  3086. {
  3087.     struct UFB * ufb;
  3088.     int result = ERROR;
  3089.  
  3090.     chkabort();
  3091.  
  3092.     ASSERT(optval != NULL && optlen != NULL);
  3093.  
  3094.     ENTER();
  3095.     SHOWVALUE(sockfd);
  3096.     SHOWVALUE(level);
  3097.     SHOWVALUE(optname);
  3098.     SHOWVALUE(optval);
  3099.     SHOWVALUE(optlen);
  3100.  
  3101.     ufb = chkufb(sockfd);
  3102.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3103.         result = getsockopt(ufb->ufbfh,level,optname,optval,(LONG *)optlen);
  3104.     else
  3105.         errno = ENOTSOCK;
  3106.  
  3107.     RETURN(result);
  3108.     return(result);
  3109. }
  3110.  
  3111. /******************************************************************************/
  3112.  
  3113. int
  3114. amiga_ioctl(int fd,unsigned long request,char *arg)
  3115. {
  3116.     struct UFB * ufb;
  3117.     int result = ERROR;
  3118.  
  3119.     chkabort();
  3120.  
  3121.     ASSERT(arg != NULL);
  3122.  
  3123.     ENTER();
  3124.     SHOWVALUE(fd);
  3125.     SHOWVALUE(request);
  3126.     SHOWVALUE(arg);
  3127.  
  3128.     ufb = chkufb(fd);
  3129.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3130.         result = IoctlSocket(ufb->ufbfh,request,arg);
  3131.     else
  3132.         errno = ENOTSOCK;
  3133.  
  3134.     RETURN(result);
  3135.     return(result);
  3136. }
  3137.  
  3138. /******************************************************************************/
  3139.  
  3140. int
  3141. amiga_listen(int sockfd,int backlog)
  3142. {
  3143.     struct UFB * ufb;
  3144.     int result = ERROR;
  3145.  
  3146.     chkabort();
  3147.  
  3148.     ENTER();
  3149.     SHOWVALUE(sockfd);
  3150.     SHOWVALUE(backlog);
  3151.  
  3152.     ufb = chkufb(sockfd);
  3153.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3154.         result = listen(ufb->ufbfh,backlog);
  3155.     else
  3156.         errno = ENOTSOCK;
  3157.  
  3158.     RETURN(result);
  3159.     return(result);
  3160. }
  3161.  
  3162. /******************************************************************************/
  3163.  
  3164. int
  3165. amiga_read(int fd,VOID *data,unsigned int size)
  3166. {
  3167.     struct UFB * ufb;
  3168.     int result;
  3169.  
  3170.     chkabort();
  3171.  
  3172.     ASSERT(data != NULL);
  3173.  
  3174.     ENTER();
  3175.     SHOWVALUE(fd);
  3176.     SHOWVALUE(data);
  3177.     SHOWVALUE(size);
  3178.  
  3179.     ufb = chkufb(fd);
  3180.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3181.     {
  3182.         SHOWMSG("input from socket");
  3183.         result = recv(ufb->ufbfh,data,size,0);
  3184.     }
  3185.     else
  3186.     {
  3187.         SHOWMSG("input from file");
  3188.         ForbidDOS();
  3189.         result = read(fd,data,size);
  3190.         PermitDOS();
  3191.     }
  3192.  
  3193.     RETURN(result);
  3194.     return(result);
  3195. }
  3196.  
  3197. /******************************************************************************/
  3198.  
  3199. int
  3200. amiga_recvfrom(int sockfd,VOID *buff,int len,int flags,struct sockaddr *from,int *fromlen)
  3201. {
  3202.     struct UFB * ufb;
  3203.     int result = ERROR;
  3204.  
  3205.     chkabort();
  3206.  
  3207.     ASSERT(buff != NULL && from != NULL && fromlen != NULL);
  3208.  
  3209.     ENTER();
  3210.     SHOWVALUE(sockfd);
  3211.     SHOWVALUE(buff);
  3212.     SHOWVALUE(len);
  3213.     SHOWVALUE(flags);
  3214.     SHOWVALUE(from);
  3215.     SHOWVALUE(fromlen);
  3216.  
  3217.     ufb = chkufb(sockfd);
  3218.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3219.         result = recvfrom(ufb->ufbfh,buff,len,flags,from,(LONG *)fromlen);
  3220.     else
  3221.         errno = ENOTSOCK;
  3222.  
  3223.     RETURN(result);
  3224.     return(result);
  3225. }
  3226.  
  3227. /******************************************************************************/
  3228.  
  3229. STATIC VOID
  3230. MapDescriptorSets(
  3231.     const fd_set *    input_fds,
  3232.     int                num_input_fds,
  3233.     fd_set *        socket_fds,
  3234.     int *            max_socket_fd_ptr,
  3235.     fd_set *        file_fds,
  3236.     int *            max_file_fd_ptr)
  3237. {
  3238.     FD_ZERO(socket_fds);
  3239.     FD_ZERO(file_fds);
  3240.  
  3241.     /* This routine maps file descriptor sets
  3242.      * from one format to another. We map
  3243.      * socket descriptors and regular file
  3244.      * descriptor sets.
  3245.      */
  3246.     if(input_fds != NULL && num_input_fds > 0)
  3247.     {
  3248.         int max_socket_fd = (*max_socket_fd_ptr);
  3249.         int max_file_fd = (*max_file_fd_ptr);
  3250.         struct UFB * ufb;
  3251.         int i;
  3252.  
  3253.         for(i = 0 ; i < num_input_fds ; i++)
  3254.         {
  3255.             if(FD_ISSET(i,input_fds))
  3256.             {
  3257.                 D(("fd to wait on #%ld",i));
  3258.  
  3259.                 ufb = chkufb(i);
  3260.                 if(ufb != NULL)
  3261.                 {
  3262.                     /* Is this a socket descriptor? */
  3263.                     if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3264.                     {
  3265.                         D(("fd #%ld is a socket.\n",i));
  3266.  
  3267.                         FD_SET(ufb->ufbfh,socket_fds);
  3268.  
  3269.                         if(max_socket_fd < ufb->ufbfh)
  3270.                             max_socket_fd = ufb->ufbfh;
  3271.                     }
  3272.                     else
  3273.                     {
  3274.                         D(("fd #%ld is a file.\n",i));
  3275.  
  3276.                         /* We only watch files bound to
  3277.                          * console streams.
  3278.                          */
  3279.                         if(IsInteractive((BPTR)ufb->ufbfh))
  3280.                         {
  3281.                             FD_SET(i,file_fds);
  3282.  
  3283.                             if(max_file_fd < i)
  3284.                                 max_file_fd = i;
  3285.                         }
  3286.                     }
  3287.                 }
  3288.             }
  3289.         }
  3290.  
  3291.         (*max_socket_fd_ptr)    = max_socket_fd;
  3292.         (*max_file_fd_ptr)        = max_file_fd;
  3293.     }
  3294. }
  3295.  
  3296. STATIC VOID
  3297. RemapDescriptorSets(
  3298.     const fd_set *    socket_fds,
  3299.     int                max_socket_fd,
  3300.     const fd_set *    file_fds,
  3301.     int                max_file_fd,
  3302.     fd_set *        output_fds,
  3303.     int                num_output_fds)
  3304. {
  3305.     /* This routine reverses the mapping established
  3306.      * above. We map the file and socket descriptor
  3307.      * sets back into the original set.
  3308.      */
  3309.     if(output_fds != NULL)
  3310.     {
  3311.         int fd;
  3312.  
  3313.         FD_ZERO(output_fds);
  3314.  
  3315.         for(fd = 0 ; fd <= max_socket_fd ; fd++)
  3316.         {
  3317.             if(FD_ISSET(fd,socket_fds))
  3318.             {
  3319.                 struct UFB * ufb;
  3320.                 int output_fd;
  3321.  
  3322.                 for(output_fd = 0 ; output_fd < num_output_fds ; output_fd++)
  3323.                 {
  3324.                     ufb = chkufb(output_fd);
  3325.                     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET) && ufb->ufbfh == fd)
  3326.                     {
  3327.                         D(("fd #%ld has data",output_fd));
  3328.                         FD_SET(output_fd,output_fds);
  3329.                         break;
  3330.                     }
  3331.                 }
  3332.             }
  3333.         }
  3334.  
  3335.         for(fd = 0 ; fd <= max_file_fd ; fd++)
  3336.         {
  3337.             if(FD_ISSET(fd,file_fds))
  3338.             {
  3339.                 D(("fd #%ld has data",fd));
  3340.                 FD_SET(fd,output_fds);
  3341.             }
  3342.         }
  3343.     }
  3344. }
  3345.  
  3346. int
  3347. amiga_select(int num_fds,fd_set *read_fds,fd_set *write_fds,fd_set *except_fds,struct timeval *timeout)
  3348. {
  3349.     fd_set socket_read_fds;
  3350.     fd_set socket_write_fds;
  3351.     fd_set socket_except_fds;
  3352.     int max_socket_fd;
  3353.     fd_set file_read_fds;
  3354.     fd_set file_write_fds;
  3355.     fd_set file_except_fds;
  3356.     struct UFB * ufb;
  3357.     int max_file_fd;
  3358.     int result = 0;
  3359.  
  3360.     chkabort();
  3361.  
  3362.     ENTER();
  3363.  
  3364.     if(num_fds > FD_SETSIZE)
  3365.     {
  3366.         D(("Warning: %ld descriptor sets to wait on requested; only %ld available.",num_fds,FD_SETSIZE));
  3367.         num_fds = FD_SETSIZE;
  3368.     }
  3369.  
  3370.     max_socket_fd = -1;
  3371.     max_file_fd = -1;
  3372.  
  3373.     MapDescriptorSets(read_fds,        num_fds,    &socket_read_fds,    &max_socket_fd,    &file_read_fds,        &max_file_fd);
  3374.     MapDescriptorSets(write_fds,    num_fds,    &socket_write_fds,    &max_socket_fd,    &file_write_fds,    &max_file_fd);
  3375.     MapDescriptorSets(except_fds,    num_fds,    &socket_except_fds,    &max_socket_fd,    &file_except_fds,    &max_file_fd);
  3376.  
  3377.     D(("number of socket fds to work on == %ld",max_socket_fd+1));
  3378.     D(("number of file   fds to work on == %ld",max_file_fd+1));
  3379.  
  3380.     /* Wait for socket input? */
  3381.     if(max_socket_fd != -1)
  3382.     {
  3383.         /* Wait for file input, too? */
  3384.         if(max_file_fd != -1 && (timeout == NULL || timeout->tv_secs > 0 || timeout->tv_micro > 0))
  3385.         {
  3386.             struct timeval stopWhen;
  3387.             struct timeval zero;
  3388.             BOOL gotSomething;
  3389.             ULONG breakMask;
  3390.             int i;
  3391.  
  3392.             /* We are going to poll all streams; for the timeout
  3393.              * feature to work, we absolutely must know when to
  3394.              * stop polling.
  3395.              *
  3396.              * Why aren't we using asynchronous DOS packets?
  3397.              * The answer is that once a packet is sent, you
  3398.              * cannot easily abort it. Polling is safer in
  3399.              * that respect. Yes, I know that ACTION_STACK
  3400.              * can be used to fake input to a console stream,
  3401.              * but I'd rather not rely upon it.
  3402.              */
  3403.             if(timeout != NULL)
  3404.             {
  3405.                 GetSysTime((APTR)&stopWhen);
  3406.                 AddTime((APTR)&stopWhen,(APTR)timeout);
  3407.             }
  3408.             else
  3409.             {
  3410.                 /* No timeout, poll until we are interrupted
  3411.                  * or get input from any of the files. It's
  3412.                  * not really necessary to initialize this
  3413.                  * timeval, but it keeps the compiler happy.
  3414.                  */
  3415.                 memset(&stopWhen,0,sizeof(stopWhen));
  3416.             }
  3417.  
  3418.             while(TRUE)
  3419.             {
  3420.                 /* Check for break signal. */
  3421.                 chkabort();
  3422.  
  3423.                 /* Delay for a tick to avoid busy-waiting. */
  3424.                 Delay(1);
  3425.  
  3426.                 /* This tells WaitSelect() to poll the sockets for input. */
  3427.                 zero.tv_secs    = 0;
  3428.                 zero.tv_micro    = 0;
  3429.  
  3430.                 /* Signals to stop on; we want to stop when a break signal arrives. */
  3431.                 if(AllowBreak)
  3432.                     breakMask = SIGBREAKF_CTRL_C;
  3433.                 else
  3434.                     breakMask = 0;
  3435.  
  3436.                 /* Check for socket input. */
  3437.                 result = WaitSelect(max_socket_fd+1,&socket_read_fds,&socket_write_fds,&socket_except_fds,&zero,&breakMask);
  3438.  
  3439.                 /* Stop if a break signal arrives. */
  3440.                 if((result < 0 && errno == EINTR) || FLAG_IS_SET(breakMask,SIGBREAKF_CTRL_C))
  3441.                     raise(SIGINT);
  3442.  
  3443.                 /* Stop if the return value from WaitSelect is negative. */
  3444.                 if(result < 0)
  3445.                     break;
  3446.  
  3447.                 /* Did we get any socket input? */
  3448.                 gotSomething = (BOOL)(result > 0);
  3449.                 if(NOT gotSomething)
  3450.                 {
  3451.                     /* Check all files for input. We also poll
  3452.                      * them for input, but each with a little
  3453.                      * delay of about 1/50 of a second. We stop
  3454.                      * as soon as we find one file that has
  3455.                      * input in it.
  3456.                      */
  3457.                     for(i = 0 ; i <= max_file_fd ; i++)
  3458.                     {
  3459.                         if(FD_ISSET(i,&file_read_fds) ||
  3460.                            FD_ISSET(i,&file_write_fds) ||
  3461.                            FD_ISSET(i,&file_except_fds))
  3462.                         {
  3463.                             ufb = chkufb(i);
  3464.                             if(ufb != NULL)
  3465.                             {
  3466.                                 if(WaitForChar((BPTR)ufb->ufbfh,1))
  3467.                                 {
  3468.                                     gotSomething = TRUE;
  3469.                                     break;
  3470.                                 }
  3471.                             }
  3472.                         }
  3473.                     }
  3474.                 }
  3475.  
  3476.                 /* Did we get any input at all? */
  3477.                 if(gotSomething)
  3478.                 {
  3479.                     BOOL gotInput;
  3480.  
  3481.                     /* Now retest all files and remember
  3482.                      * those that had input.
  3483.                      */
  3484.                     for(i = 0 ; i <= max_file_fd ; i++)
  3485.                     {
  3486.                         gotInput = FALSE;
  3487.  
  3488.                         if(FD_ISSET(i,&file_read_fds) ||
  3489.                            FD_ISSET(i,&file_write_fds) ||
  3490.                            FD_ISSET(i,&file_except_fds))
  3491.                         {
  3492.                             ufb = chkufb(i);
  3493.                             if(ufb != NULL)
  3494.                             {
  3495.                                 /* Does this one have input? */
  3496.                                 gotInput = WaitForChar((BPTR)ufb->ufbfh,1);
  3497.                             }
  3498.                         }
  3499.  
  3500.                         if(gotInput)
  3501.                         {
  3502.                             /* Mark one more descriptor as
  3503.                              * having input.
  3504.                              */
  3505.                             result++;
  3506.                         }
  3507.                         else
  3508.                         {
  3509.                             /* Mark this descriptor as
  3510.                              * not having any input.
  3511.                              */
  3512.                             FD_CLR(i,&file_read_fds);
  3513.                             FD_CLR(i,&file_write_fds);
  3514.                             FD_CLR(i,&file_except_fds);
  3515.                         }
  3516.                     }
  3517.                 }
  3518.  
  3519.                 /* Did we get any input? If so, stop polling. */
  3520.                 if(result > 0)
  3521.                     break;
  3522.  
  3523.                 /* If a timeout was set, check if we are already
  3524.                  * beyond the point of time when we should have
  3525.                  * stopped polling.
  3526.                  */
  3527.                 if(timeout != NULL)
  3528.                 {
  3529.                     struct timeval now;
  3530.  
  3531.                     GetSysTime((APTR)&now);
  3532.  
  3533.                     if((-CmpTime((APTR)&now,(APTR)&stopWhen)) >= 0)
  3534.                         break;
  3535.                 }
  3536.             }
  3537.         }
  3538.         else
  3539.         {
  3540.             ULONG breakMask;
  3541.  
  3542.             if(AllowBreak)
  3543.                 breakMask = SIGBREAKF_CTRL_C;
  3544.             else
  3545.                 breakMask = 0;
  3546.  
  3547.             result = WaitSelect(max_socket_fd+1,&socket_read_fds,&socket_write_fds,&socket_except_fds,timeout,&breakMask);
  3548.             if((result < 0 && errno == EINTR) || FLAG_IS_SET(breakMask,SIGBREAKF_CTRL_C))
  3549.                 raise(SIGINT);
  3550.         }
  3551.     }
  3552.     else
  3553.     {
  3554.         /* Wait for file input? */
  3555.         if(max_file_fd != -1 && (timeout == NULL || timeout->tv_secs > 0 || timeout->tv_micro > 0))
  3556.         {
  3557.             struct timeval stopWhen;
  3558.             BOOL gotSomething;
  3559.             int i;
  3560.  
  3561.             if(timeout != NULL)
  3562.             {
  3563.                 GetSysTime((APTR)&stopWhen);
  3564.                 AddTime((APTR)&stopWhen,(APTR)timeout);
  3565.             }
  3566.             else
  3567.             {
  3568.                 memset(&stopWhen,0,sizeof(stopWhen));
  3569.             }
  3570.  
  3571.             while(TRUE)
  3572.             {
  3573.                 chkabort();
  3574.  
  3575.                 Delay(1);
  3576.  
  3577.                 gotSomething = FALSE;
  3578.                 for(i = 0 ; i <= max_file_fd ; i++)
  3579.                 {
  3580.                     if(FD_ISSET(i,&file_read_fds) ||
  3581.                        FD_ISSET(i,&file_write_fds) ||
  3582.                        FD_ISSET(i,&file_except_fds))
  3583.                     {
  3584.                         ufb = chkufb(i);
  3585.                         if(ufb != NULL)
  3586.                         {
  3587.                             if(WaitForChar((BPTR)ufb->ufbfh,1))
  3588.                             {
  3589.                                 gotSomething = TRUE;
  3590.                                 break;
  3591.                             }
  3592.                         }
  3593.                     }
  3594.                 }
  3595.  
  3596.                 if(gotSomething)
  3597.                 {
  3598.                     BOOL gotInput;
  3599.  
  3600.                     for(i = 0 ; i <= max_file_fd ; i++)
  3601.                     {
  3602.                         gotInput = FALSE;
  3603.  
  3604.                         if(FD_ISSET(i,&file_read_fds) ||
  3605.                            FD_ISSET(i,&file_write_fds) ||
  3606.                            FD_ISSET(i,&file_except_fds))
  3607.                         {
  3608.                             ufb = chkufb(i);
  3609.                             if(ufb != NULL)
  3610.                             {
  3611.                                 /* Does this one have input? */
  3612.                                 gotInput = WaitForChar((BPTR)ufb->ufbfh,1);
  3613.                             }
  3614.                         }
  3615.  
  3616.                         if(gotInput)
  3617.                         {
  3618.                             result++;
  3619.                         }
  3620.                         else
  3621.                         {
  3622.                             FD_CLR(i,&file_read_fds);
  3623.                             FD_CLR(i,&file_write_fds);
  3624.                             FD_CLR(i,&file_except_fds);
  3625.                         }
  3626.                     }
  3627.                 }
  3628.  
  3629.                 if(result > 0)
  3630.                     break;
  3631.  
  3632.                 if(timeout != NULL)
  3633.                 {
  3634.                     struct timeval now;
  3635.  
  3636.                     GetSysTime((APTR)&now);
  3637.  
  3638.                     if((-CmpTime((APTR)&now,(APTR)&stopWhen)) >= 0)
  3639.                         break;
  3640.                 }
  3641.             }
  3642.         }
  3643.     }
  3644.  
  3645.     /* The descriptor sets remain unchanged in
  3646.      * case of error.
  3647.      */
  3648.     if(result >= 0)
  3649.     {
  3650.         RemapDescriptorSets(&socket_read_fds,    max_socket_fd,    &file_read_fds,        max_file_fd,    read_fds,    num_fds);
  3651.         RemapDescriptorSets(&socket_write_fds,    max_socket_fd,    &file_write_fds,    max_file_fd,    write_fds,    num_fds);
  3652.         RemapDescriptorSets(&socket_except_fds,    max_socket_fd,    &file_except_fds,    max_file_fd,    except_fds,    num_fds);
  3653.     }
  3654.  
  3655.     RETURN(result);
  3656.     return(result);
  3657. }
  3658.  
  3659. /******************************************************************************/
  3660.  
  3661. int
  3662. amiga_sendto(int sockfd,VOID *buff,int len,int flags,struct sockaddr *to,int tolen)
  3663. {
  3664.     struct UFB * ufb;
  3665.     int result = ERROR;
  3666.  
  3667.     chkabort();
  3668.  
  3669.     ASSERT(buff != NULL && to != NULL);
  3670.  
  3671.     ENTER();
  3672.     SHOWVALUE(sockfd);
  3673.     SHOWVALUE(buff);
  3674.     SHOWVALUE(len);
  3675.     SHOWVALUE(flags);
  3676.     SHOWVALUE(to);
  3677.     SHOWVALUE(tolen);
  3678.  
  3679.     ufb = chkufb(sockfd);
  3680.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3681.         result = sendto(ufb->ufbfh,buff,len,flags,to,tolen);
  3682.     else
  3683.         errno = ENOTSOCK;
  3684.  
  3685.     RETURN(result);
  3686.     return(result);
  3687. }
  3688.  
  3689. /******************************************************************************/
  3690.  
  3691. int
  3692. amiga_setsockopt(int sockfd,int level,int optname,VOID *optval,int optlen)
  3693. {
  3694.     struct UFB * ufb;
  3695.     int result = ERROR;
  3696.  
  3697.     chkabort();
  3698.  
  3699.     ASSERT(optval != NULL);
  3700.  
  3701.     ENTER();
  3702.     SHOWVALUE(sockfd);
  3703.     SHOWVALUE(level);
  3704.     SHOWVALUE(optname);
  3705.     SHOWVALUE(optval);
  3706.     SHOWVALUE(optlen);
  3707.  
  3708.     ufb = chkufb(sockfd);
  3709.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3710.         result = setsockopt(ufb->ufbfh,level,optname,optval,optlen);
  3711.     else
  3712.         errno = ENOTSOCK;
  3713.  
  3714.     RETURN(result);
  3715.     return(result);
  3716. }
  3717.  
  3718. /******************************************************************************/
  3719.  
  3720. int
  3721. amiga_socket(int domain,int type,int protocol)
  3722. {
  3723.     int result = ERROR;
  3724.     int fd;
  3725.  
  3726.     chkabort();
  3727.  
  3728.     ENTER();
  3729.     SHOWVALUE(domain);
  3730.     SHOWVALUE(type);
  3731.     SHOWVALUE(protocol);
  3732.  
  3733.     /* We open a regular file that is guaranteed to
  3734.      * open in any case and then attach a socket
  3735.      * in place of the original file handle.
  3736.      */
  3737.     fd = open("NIL:",O_RDWR,0777);
  3738.     if(fd != -1)
  3739.     {
  3740.         struct UFB * ufb;
  3741.  
  3742.         ufb = chkufb(fd);
  3743.         if(ufb != NULL)
  3744.         {
  3745.             /* Save the original file handle value. */
  3746.             if(SaveDescriptor(ufb))
  3747.             {
  3748.                 int sockfd;
  3749.  
  3750.                 /* Now create the real socket. */
  3751.                 sockfd = socket(domain,type,protocol);
  3752.                 if(sockfd != -1)
  3753.                 {
  3754.                     /* Put the socket in place of the file handle. */
  3755.                     SET_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  3756.                     ufb->ufbfh = sockfd;
  3757.  
  3758.                     result = fd;
  3759.                 }
  3760.                 else
  3761.                 {
  3762.                     close(fd);
  3763.                 }
  3764.             }
  3765.             else
  3766.             {
  3767.                 close(fd);
  3768.                 errno = ENOMEM;
  3769.             }
  3770.         }
  3771.         else
  3772.         {
  3773.             close(fd);
  3774.             errno = EBADF;
  3775.         }
  3776.     }
  3777.  
  3778.     RETURN(result);
  3779.     return(result);
  3780. }
  3781.  
  3782. /******************************************************************************/
  3783.  
  3784. int
  3785. amiga_write(int fd,VOID *data,unsigned int size)
  3786. {
  3787.     struct UFB * ufb;
  3788.     int result;
  3789.  
  3790.     chkabort();
  3791.  
  3792.     ASSERT(data != NULL);
  3793.  
  3794.     ENTER();
  3795.     SHOWVALUE(fd);
  3796.     SHOWVALUE(data);
  3797.     SHOWVALUE(size);
  3798.  
  3799.     ufb = chkufb(fd);
  3800.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3801.     {
  3802.         result = send(ufb->ufbfh,data,size,0);
  3803.     }
  3804.     else
  3805.     {
  3806.         ForbidDOS();
  3807.         result = write(fd,data,size);
  3808.         PermitDOS();
  3809.     }
  3810.  
  3811.     RETURN(result);
  3812.     return(result);
  3813. }
  3814.  
  3815. /******************************************************************************/
  3816.  
  3817. STATIC VOID
  3818. ConvertFileInfoToStat(
  3819.     struct MsgPort * port,
  3820.     struct FileInfoBlock * fib,
  3821.     struct stat * st)
  3822. {
  3823.     ULONG flags;
  3824.     int mode;
  3825.     long time;
  3826.  
  3827.     /* This routine converts the contents of a FileInfoBlock
  3828.      * into information to fill a Unix-like stat data structure
  3829.      * with.
  3830.      */
  3831.     flags = fib->fib_Protection ^ (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  3832.  
  3833.     if(FIB_IS_DRAWER(fib))
  3834.         mode = S_IFDIR;
  3835.     else
  3836.         mode = S_IFREG;
  3837.  
  3838.     if(FLAG_IS_SET(flags,FIBF_READ))
  3839.         SET_FLAG(mode,S_IRUSR);
  3840.  
  3841.     if(FLAG_IS_SET(flags,FIBF_WRITE) && FLAG_IS_SET(flags,FIBF_DELETE))
  3842.         SET_FLAG(mode,S_IWUSR);
  3843.  
  3844.     if(FLAG_IS_SET(flags,FIBF_EXECUTE))
  3845.         SET_FLAG(mode,S_IXUSR);
  3846.  
  3847.  
  3848.     if(FLAG_IS_SET(flags,FIBF_GRP_READ))
  3849.         SET_FLAG(mode,S_IRGRP);
  3850.  
  3851.     if(FLAG_IS_SET(flags,FIBF_GRP_WRITE) && FLAG_IS_SET(flags,FIBF_GRP_DELETE))
  3852.         SET_FLAG(mode,S_IWGRP);
  3853.  
  3854.     if(FLAG_IS_SET(flags,FIBF_GRP_EXECUTE))
  3855.         SET_FLAG(mode,S_IXGRP);
  3856.  
  3857.  
  3858.     if(FLAG_IS_SET(flags,FIBF_OTR_READ))
  3859.         SET_FLAG(mode,S_IROTH);
  3860.  
  3861.     if(FLAG_IS_SET(flags,FIBF_OTR_WRITE) && FLAG_IS_SET(flags,FIBF_OTR_DELETE))
  3862.         SET_FLAG(mode,S_IWOTH);
  3863.  
  3864.     if(FLAG_IS_SET(flags,FIBF_OTR_EXECUTE))
  3865.         SET_FLAG(mode,S_IXOTH);
  3866.  
  3867.     time = fib->fib_Date.ds_Days * 24*60*60 +
  3868.            fib->fib_Date.ds_Minute * 60 +
  3869.           (fib->fib_Date.ds_Tick / TICKS_PER_SECOND);
  3870.  
  3871.     memset(st,0,sizeof(*st));
  3872.  
  3873.     st->st_dev        = (u_long)port;
  3874.     st->st_ino        = fib->fib_DiskKey;
  3875.     st->st_mode        = mode;
  3876.     st->st_mtime    = UNIX_TIME_OFFSET + time + 60*MinutesWest;    /* translate from local time to UTC */
  3877.     st->st_atime    = st->st_mtime;
  3878.     st->st_ctime    = st->st_mtime;
  3879.     st->st_uid        = fib->fib_OwnerUID;
  3880.     st->st_gid        = fib->fib_OwnerGID;
  3881.  
  3882.     if(FIB_IS_FILE(fib))
  3883.     {
  3884.         st->st_nlink = 1;
  3885.         st->st_size  = fib->fib_Size;
  3886.     }
  3887.     else
  3888.     {
  3889.         st->st_nlink = 2;
  3890.     }
  3891. }
  3892.  
  3893. int
  3894. amiga_stat(char *name, struct stat *st)
  3895. {
  3896.     char localName[MAX_FILENAME_LEN];
  3897.     struct MangleInfo mi;
  3898.     int result = ERROR;
  3899.  
  3900.     chkabort();
  3901.  
  3902.     ASSERT(name != NULL && st != NULL);
  3903.  
  3904.     ENTER();
  3905.     SHOWSTRING(name);
  3906.     SHOWVALUE(st);
  3907.  
  3908.     if(TranslateRelativePath(&name,localName,sizeof(localName)) == OK)
  3909.     {
  3910.         char * originalName = name;
  3911.  
  3912.         if(MangleName(&name,&mi) == OK)
  3913.         {
  3914.             int len;
  3915.  
  3916.             SHOWSTRING(name);
  3917.             SHOWSTRING(originalName);
  3918.  
  3919.             len = strlen(name);
  3920.             if((strcmp(originalName,"/") == SAME) || (len > 1 && name[len-2] == ':' && name[len-1] == '/'))
  3921.             {
  3922.                 struct timeval now;
  3923.  
  3924.                 SHOWMSG("this is the virtual root directory");
  3925.  
  3926.                 /* This must be our virtual root directory.
  3927.                  * Make something up.
  3928.                  */
  3929.                 memset(st,0,sizeof(*st));
  3930.                 GetSysTime((APTR)&now);
  3931.  
  3932.                 /* Nobody may write to this "directory". */
  3933.                 st->st_dev        = (u_long)"Virtual Root Directory";
  3934.                 st->st_ino        = 1;
  3935.                 st->st_mode        = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
  3936.                 st->st_nlink    = 2;
  3937.                 st->st_mtime    = UNIX_TIME_OFFSET + now.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  3938.                 st->st_atime    = st->st_mtime;
  3939.                 st->st_ctime    = st->st_mtime;
  3940.  
  3941.                 result = OK;
  3942.             }
  3943.             else
  3944.             {
  3945.                 BPTR fileLock;
  3946.  
  3947.                 SHOWMSG("this is a drawer or a file");
  3948.  
  3949.                 ForbidDOS();
  3950.  
  3951.                 fileLock = Lock((STRPTR)name,SHARED_LOCK);
  3952.                 if(fileLock != ZERO)
  3953.                 {
  3954.                     D_S(struct FileInfoBlock,fib);
  3955.  
  3956.                     if(Examine(fileLock,fib))
  3957.                     {
  3958.                         BPTR parentDir;
  3959.  
  3960.                         /* Check if this is the root directory. */
  3961.                         parentDir = ParentDir(fileLock);
  3962.                         if(parentDir != ZERO)
  3963.                         {
  3964.                             /* This is not the root directory. */
  3965.                             UnLock(parentDir);
  3966.                         }
  3967.                         else
  3968.                         {
  3969.                             /* So this is the root directory. Make sure
  3970.                              * that we return proper protection bits for
  3971.                              * it, i.e. that the directory is always
  3972.                              * readable, writable, etc. This may be
  3973.                              * necessary since on the Amiga, root
  3974.                              * directories cannot have any protection
  3975.                              * bits set. Note that the "deletable"
  3976.                              * bits don't make much sense, but then
  3977.                              * these bits work together with the
  3978.                              * writable bits. The lowest four bits
  3979.                              * remain zero, which enables them all.
  3980.                              */
  3981.                             fib->fib_Protection = FIBF_OTR_READ |
  3982.                                                   FIBF_OTR_WRITE |
  3983.                                                   FIBF_OTR_EXECUTE |
  3984.                                                   FIBF_OTR_DELETE |
  3985.                                                   FIBF_GRP_READ |
  3986.                                                   FIBF_GRP_WRITE |
  3987.                                                   FIBF_GRP_EXECUTE |
  3988.                                                   FIBF_GRP_DELETE;
  3989.                         }
  3990.  
  3991.                         ConvertFileInfoToStat(((struct FileLock *)BADDR(fileLock))->fl_Task,fib,st);
  3992.  
  3993.                         result = OK;
  3994.                     }
  3995.                     else
  3996.                     {
  3997.                         MapIoErrToErrno();
  3998.                     }
  3999.  
  4000.                     UnLock(fileLock);
  4001.                 }
  4002.                 else
  4003.                 {
  4004.                     LONG error = IoErr();
  4005.  
  4006.                     if(error == ERROR_OBJECT_IN_USE)
  4007.                     {
  4008.                         char parentName[MAX_FILENAME_LEN];
  4009.                         BPTR parentLock;
  4010.  
  4011.                         strcpy(parentName,name);
  4012.                         (*PathPart(parentName) = '\0');
  4013.  
  4014.                         parentLock = Lock(parentName,SHARED_LOCK);
  4015.                         if(parentLock != ZERO)
  4016.                         {
  4017.                             D_S(struct FileInfoBlock,fib);
  4018.  
  4019.                             if(Examine(parentLock,fib))
  4020.                             {
  4021.                                 STRPTR onlyFileName = FilePart(name);
  4022.  
  4023.                                 while(ExNext(parentLock,fib))
  4024.                                 {
  4025.                                     if(Stricmp(fib->fib_FileName,onlyFileName) == SAME)
  4026.                                     {
  4027.                                         ConvertFileInfoToStat(((struct FileLock *)BADDR(parentLock))->fl_Task,fib,st);
  4028.  
  4029.                                         result = OK;
  4030.                                         error = OK;
  4031.                                         break;
  4032.                                     }
  4033.                                 }
  4034.                             }
  4035.  
  4036.                             UnLock(parentLock);
  4037.                         }
  4038.                     }
  4039.  
  4040.                     if(error != OK)
  4041.                     {
  4042.                         SetIoErr(error);
  4043.  
  4044.                         MapIoErrToErrno();
  4045.                     }
  4046.                 }
  4047.  
  4048.                 PermitDOS();
  4049.             }
  4050.  
  4051.             if(result == OK)
  4052.             {
  4053.                 SHOWVALUE(st->st_dev);
  4054.                 SHOWVALUE(st->st_ino);
  4055.                 SHOWVALUE(st->st_size);
  4056.                 SHOWVALUE(st->st_nlink);
  4057.                 SHOWVALUE(st->st_mode);
  4058.                 SHOWVALUE(st->st_mtime);
  4059.                 SHOWVALUE(st->st_atime);
  4060.                 SHOWVALUE(st->st_ctime);
  4061.                 SHOWVALUE(st->st_uid);
  4062.                 SHOWVALUE(st->st_gid);
  4063.             }
  4064.             else
  4065.             {
  4066.                 SHOWVALUE(errno);
  4067.             }
  4068.  
  4069.             UnmangleName(&name,&mi);
  4070.         }
  4071.     }
  4072.  
  4073.     RETURN(result);
  4074.     return(result);
  4075. }
  4076.  
  4077. int
  4078. amiga_lstat(char *name, struct stat *statstruct)
  4079. {
  4080.     int result;
  4081.  
  4082.     chkabort();
  4083.  
  4084.     ENTER();
  4085.     SHOWSTRING(name);
  4086.     SHOWVALUE(statstruct);
  4087.  
  4088.     result = amiga_stat(name,statstruct);
  4089.  
  4090.     RETURN(result);
  4091.     return(result);
  4092. }
  4093.  
  4094. int
  4095. amiga_fstat(int fd,struct stat * st)
  4096. {
  4097.     struct UFB * ufb;
  4098.     int result = ERROR;
  4099.  
  4100.     chkabort();
  4101.  
  4102.     ASSERT(st != NULL);
  4103.  
  4104.     ENTER();
  4105.     SHOWVALUE(fd);
  4106.     SHOWVALUE(st);
  4107.  
  4108.     ufb = chkufb(fd);
  4109.     if(ufb != NULL)
  4110.     {
  4111.         if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  4112.         {
  4113.             long value;
  4114.             long size = sizeof(value);
  4115.  
  4116.             memset(st,0,sizeof(*st));
  4117.  
  4118.             st->st_dev    = (u_long)SocketBase;
  4119.             st->st_mode    = S_IFSOCK | S_IRUSR | S_IWUSR;
  4120.             st->st_uid    = geteuid();
  4121.             st->st_gid    = getegid();
  4122.  
  4123.             if(getsockopt(fd,SOL_SOCKET,SO_SNDBUF,&value,&size) == 0)
  4124.                 st->st_blksize = value;
  4125.  
  4126.             result = OK;
  4127.         }
  4128.         else
  4129.         {
  4130.             struct FileHandle * fileHandle = BADDR(ufb->ufbfh);
  4131.  
  4132.             /* Make sure that this stream doesn't
  4133.              * really refer to "NIL:".
  4134.              */
  4135.             if(fileHandle->fh_Type != NULL)
  4136.             {
  4137.                 D_S(struct FileInfoBlock,fib);
  4138.  
  4139.                 ForbidDOS();
  4140.  
  4141.                 if(ExamineFH(ufb->ufbfh,fib))
  4142.                 {
  4143.                     ConvertFileInfoToStat(fileHandle->fh_Type,fib,st);
  4144.  
  4145.                     result = OK;
  4146.                 }
  4147.                 else
  4148.                 {
  4149.                     MapIoErrToErrno();
  4150.                 }
  4151.  
  4152.                 PermitDOS();
  4153.             }
  4154.             else
  4155.             {
  4156.                 struct timeval tv;
  4157.  
  4158.                 /* Make up some phony data for a NIL: file handle. */
  4159.                 memset(st,0,sizeof(*st));
  4160.  
  4161.                 GetSysTime((APTR)&tv);
  4162.  
  4163.                 st->st_dev        = (u_long)0;
  4164.                 st->st_mode        = S_IFREG | S_IRUSR | S_IWUSR;
  4165.                 st->st_mtime    = UNIX_TIME_OFFSET + tv.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  4166.                 st->st_atime    = st->st_mtime;
  4167.                 st->st_ctime    = st->st_mtime;
  4168.  
  4169.                 result = OK;
  4170.             }
  4171.         }
  4172.     }
  4173.     else
  4174.     {
  4175.         errno = EBADF;
  4176.     }
  4177.  
  4178.     RETURN(result);
  4179.     return(result);
  4180. }
  4181.  
  4182. /******************************************************************************/
  4183.  
  4184. int
  4185. amiga_chmod(char *name,int mode)
  4186. {
  4187.     struct MangleInfo mi;
  4188.     ULONG flags = 0;
  4189.     int result = ERROR;
  4190.  
  4191.     chkabort();
  4192.  
  4193.     ASSERT(name != NULL);
  4194.  
  4195.     ENTER();
  4196.     SHOWSTRING(name);
  4197.     SHOWVALUE(mode);
  4198.  
  4199.     /* Convert the file access modes into
  4200.      * Amiga typical protection bits.
  4201.      */
  4202.     if(FLAG_IS_SET(mode,S_IRUSR))
  4203.         SET_FLAG(flags,FIBF_READ);
  4204.  
  4205.     if(FLAG_IS_SET(mode,S_IWUSR))
  4206.     {
  4207.         SET_FLAG(flags,FIBF_WRITE);
  4208.         SET_FLAG(flags,FIBF_DELETE);
  4209.     }
  4210.  
  4211.     if(FLAG_IS_SET(mode,S_IXUSR))
  4212.         SET_FLAG(flags,FIBF_EXECUTE);
  4213.  
  4214.  
  4215.     if(FLAG_IS_SET(mode,S_IRGRP))
  4216.         SET_FLAG(flags,FIBF_GRP_READ);
  4217.  
  4218.     if(FLAG_IS_SET(mode,S_IWGRP))
  4219.     {
  4220.         SET_FLAG(flags,FIBF_GRP_WRITE);
  4221.         SET_FLAG(flags,FIBF_GRP_DELETE);
  4222.     }
  4223.  
  4224.     if(FLAG_IS_SET(mode,S_IXGRP))
  4225.         SET_FLAG(flags,FIBF_GRP_EXECUTE);
  4226.  
  4227.  
  4228.     if(FLAG_IS_SET(mode,S_IROTH))
  4229.         SET_FLAG(flags,FIBF_OTR_READ);
  4230.  
  4231.     if(FLAG_IS_SET(mode,S_IWOTH))
  4232.     {
  4233.         SET_FLAG(flags,FIBF_OTR_WRITE);
  4234.         SET_FLAG(flags,FIBF_OTR_DELETE);
  4235.     }
  4236.  
  4237.     if(FLAG_IS_SET(mode,S_IXOTH))
  4238.         SET_FLAG(flags,FIBF_OTR_EXECUTE);
  4239.  
  4240.     flags ^= (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  4241.  
  4242.     if(MangleName(&name,&mi) == OK)
  4243.     {
  4244.         ForbidDOS();
  4245.  
  4246.         if(SetProtection(name,flags))
  4247.         {
  4248.             result = OK;
  4249.         }
  4250.         else
  4251.         {
  4252.             LONG error = IoErr();
  4253.  
  4254.             /* Note sure about this one; is it really that important
  4255.              * that the file attribute change succeeds? This is a definite
  4256.              * FIXME.
  4257.              */
  4258.             if(error == ERROR_OBJECT_IN_USE)
  4259.             {
  4260.                 result = OK;
  4261.             }
  4262.             else
  4263.             {
  4264.                 SetIoErr(error);
  4265.  
  4266.                 MapIoErrToErrno();
  4267.             }
  4268.         }
  4269.  
  4270.         PermitDOS();
  4271.  
  4272.         UnmangleName(&name,&mi);
  4273.     }
  4274.  
  4275.     RETURN(result);
  4276.     return(result);
  4277. }
  4278.  
  4279. /******************************************************************************/
  4280.  
  4281. int
  4282. amiga_dup(int fd)
  4283. {
  4284.     struct UFB * ufb;
  4285.     int result = ERROR;
  4286.  
  4287.     chkabort();
  4288.  
  4289.     ENTER();
  4290.     SHOWVALUE(fd);
  4291.  
  4292.     ufb = chkufb(fd);
  4293.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  4294.     {
  4295.         fd = open("NIL:",O_RDWR,0777);
  4296.         if(fd != -1)
  4297.         {
  4298.             struct UFB * ufb2;
  4299.  
  4300.             ufb2 = chkufb(fd);
  4301.             if(ufb2 != NULL)
  4302.             {
  4303.                 if(SaveDescriptor(ufb2))
  4304.                 {
  4305.                     int sockfd;
  4306.  
  4307.                     sockfd = Dup2Socket(ufb->ufbfh,-1);
  4308.                     if(sockfd != -1)
  4309.                     {
  4310.                         SET_FLAG(ufb2->ufbflg,UFB_IS_SOCKET);
  4311.                         ufb2->ufbfh = sockfd;
  4312.  
  4313.                         result = fd;
  4314.                     }
  4315.                     else
  4316.                     {
  4317.                         close(fd);
  4318.                     }
  4319.                 }
  4320.                 else
  4321.                 {
  4322.                     close(fd);
  4323.                     errno = ENOMEM;
  4324.                 }
  4325.             }
  4326.             else
  4327.             {
  4328.                 close(fd);
  4329.                 errno = EBADF;
  4330.             }
  4331.         }
  4332.     }
  4333.     else
  4334.     {
  4335.         errno = ENOTSOCK;
  4336.     }
  4337.  
  4338.     RETURN(result);
  4339.     return(result);
  4340. }
  4341.  
  4342. /******************************************************************************/
  4343.  
  4344. int
  4345. amiga_dup2(int old_fd,int new_fd)
  4346. {
  4347.     struct UFB * old_ufb;
  4348.     struct UFB * new_ufb;
  4349.     int result = ERROR;
  4350.  
  4351.     chkabort();
  4352.  
  4353.     ENTER();
  4354.     SHOWVALUE(old_fd);
  4355.     SHOWVALUE(new_fd);
  4356.  
  4357.     old_ufb = chkufb(old_fd);
  4358.     new_ufb = chkufb(new_fd);
  4359.  
  4360.     if(old_ufb != NULL && FLAG_IS_SET(old_ufb->ufbflg,UFB_IS_SOCKET) && new_ufb != NULL)
  4361.     {
  4362.         int sockfd;
  4363.  
  4364.         if(FLAG_IS_SET(new_ufb->ufbflg,UFB_IS_SOCKET))
  4365.         {
  4366.             CloseSocket(new_ufb->ufbfh);
  4367.             sockfd = Dup2Socket(old_ufb->ufbfh,new_ufb->ufbfh);
  4368.         }
  4369.         else
  4370.         {
  4371.             if(SaveDescriptor(new_ufb))
  4372.             {
  4373.                 sockfd = Dup2Socket(old_ufb->ufbfh,-1);
  4374.             }
  4375.             else
  4376.             {
  4377.                 sockfd = -1;
  4378.                 errno = ENOMEM;
  4379.             }
  4380.         }
  4381.  
  4382.         if(sockfd != -1)
  4383.         {
  4384.             SET_FLAG(new_ufb->ufbflg,UFB_IS_SOCKET);
  4385.             new_ufb->ufbfh = sockfd;
  4386.  
  4387.             result = new_fd;
  4388.         }
  4389.     }
  4390.     else
  4391.     {
  4392.         errno = ENOTSOCK;
  4393.     }
  4394.  
  4395.     RETURN(result);
  4396.     return(result);
  4397. }
  4398.  
  4399. /******************************************************************************/
  4400.  
  4401. struct bcpl_name
  4402. {
  4403.     unsigned char name[MAX_BSTR_LEN];
  4404. };
  4405.  
  4406. int
  4407. amiga_chown(char *name,uid_t uid,gid_t gid)
  4408. {
  4409.     struct MangleInfo mi;
  4410.     int result = ERROR;
  4411.  
  4412.     chkabort();
  4413.  
  4414.     ASSERT(name != NULL);
  4415.  
  4416.     ENTER();
  4417.     SHOWSTRING(name);
  4418.     SHOWVALUE(uid);
  4419.     SHOWVALUE(gid);
  4420.  
  4421.     if(MangleName(&name,&mi) == OK)
  4422.     {
  4423.         /* AmigaDOS 3.0 and up have a SetOwner() call. */
  4424.         if(DOSBase->lib_Version >= 39)
  4425.         {
  4426.             if(SetOwner(name,(((LONG)uid) << 16) | gid))
  4427.                 result = OK;
  4428.             else
  4429.                 MapIoErrToErrno();
  4430.         }
  4431.         else
  4432.         {
  4433.             struct DevProc * dvp;
  4434.  
  4435.             /* For 2.04 and 2.1 we'll have to do this
  4436.              * manually...
  4437.              */
  4438.             dvp = GetDeviceProc(name,NULL);
  4439.             if(dvp != NULL)
  4440.             {
  4441.                 D_S(struct bcpl_name,newName);
  4442.                 int len;
  4443.  
  4444.                 len = strlen(name);
  4445.                 if(len > sizeof(newName->name)-1)
  4446.                     len = sizeof(newName->name)-1;
  4447.  
  4448.                 newName->name[0] = len;
  4449.                 strncpy(&newName->name[1],name,len);
  4450.  
  4451.                 /* This is almost identical in operation to ACTION_SET_PROTECTION. */
  4452.                 if(DoPkt(dvp->dvp_Port,ACTION_SET_OWNER,dvp->dvp_Lock,MKBADDR(newName),(((LONG)uid) << 16) | gid,0,0))
  4453.                     result = OK;
  4454.                 else
  4455.                     MapIoErrToErrno();
  4456.  
  4457.                 FreeDeviceProc(dvp);
  4458.             }
  4459.             else
  4460.             {
  4461.                 MapIoErrToErrno();
  4462.             }
  4463.         }
  4464.  
  4465.         UnmangleName(&name,&mi);
  4466.     }
  4467.  
  4468.     RETURN(result);
  4469.     return(result);
  4470. }
  4471.  
  4472. /******************************************************************************/
  4473.  
  4474. int
  4475. amiga_setegid(gid_t g)
  4476. {
  4477.     int result;
  4478.  
  4479.     chkabort();
  4480.  
  4481.     ENTER();
  4482.     SHOWVALUE(g);
  4483.  
  4484.     result = setregid(-1,g);
  4485.  
  4486.     RETURN(result);
  4487.     return(result);
  4488. }
  4489.  
  4490. /******************************************************************************/
  4491.  
  4492. int
  4493. amiga_seteuid(uid_t u)
  4494. {
  4495.     int result;
  4496.  
  4497.     chkabort();
  4498.  
  4499.     ENTER();
  4500.     SHOWVALUE(u);
  4501.     result = setreuid(-1,u);
  4502.  
  4503.     RETURN(result);
  4504.     return(result);
  4505. }
  4506.  
  4507. /******************************************************************************/
  4508.  
  4509. int
  4510. amiga_gettimeofday(struct timeval *tv)
  4511. {
  4512.     chkabort();
  4513.  
  4514.     ENTER();
  4515.     SHOWVALUE(tv);
  4516.  
  4517.     if(tv != NULL)
  4518.     {
  4519.         GetSysTime((APTR)tv);
  4520.         tv->tv_secs += UNIX_TIME_OFFSET + 60*MinutesWest;    /* translate from local time to UTC */
  4521.  
  4522.         SHOWVALUE(tv->tv_secs);
  4523.         SHOWVALUE(tv->tv_micro);
  4524.     }
  4525.  
  4526.     RETURN(0);
  4527.     return(0);
  4528. }
  4529.  
  4530. /******************************************************************************/
  4531.  
  4532. int
  4533. amiga_utime(char *name,struct utimbuf *time)
  4534. {
  4535.     struct MangleInfo mi;
  4536.     struct DateStamp ds;
  4537.     int result = ERROR;
  4538.  
  4539.     chkabort();
  4540.  
  4541.     ASSERT(name != NULL);
  4542.  
  4543.     ENTER();
  4544.     SHOWSTRING(name);
  4545.     SHOWVALUE(time);
  4546.  
  4547.     /* Use the current time? */
  4548.     if(time == NULL)
  4549.     {
  4550.         DateStamp(&ds);
  4551.     }
  4552.     else
  4553.     {
  4554.         ULONG seconds;
  4555.  
  4556.         /* Convert the time given. */
  4557.         if(time->modtime < (UNIX_TIME_OFFSET + 60*MinutesWest))
  4558.             seconds = 0;
  4559.         else
  4560.             seconds = time->modtime - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  4561.  
  4562.         ds.ds_Days        = (seconds / (24*60*60));
  4563.         ds.ds_Minute    = (seconds % (24*60*60)) / 60;
  4564.         ds.ds_Tick        = (seconds               % 60) * TICKS_PER_SECOND;
  4565.     }
  4566.  
  4567.     if(MangleName(&name,&mi) == OK)
  4568.     {
  4569.         ForbidDOS();
  4570.  
  4571.         if(SetFileDate((STRPTR)name,&ds))
  4572.         {
  4573.             result = OK;
  4574.         }
  4575.         else
  4576.         {
  4577.             LONG error = IoErr();
  4578.  
  4579.             /* Note sure about this one; is it really that important
  4580.              * that the file date change succeeds? This is a definite
  4581.              * FIXME.
  4582.              */
  4583.             if(error == ERROR_OBJECT_IN_USE)
  4584.             {
  4585.                 result = OK;
  4586.             }
  4587.             else
  4588.             {
  4589.                 SetIoErr(error);
  4590.  
  4591.                 MapIoErrToErrno();
  4592.             }
  4593.         }
  4594.  
  4595.         PermitDOS();
  4596.  
  4597.         UnmangleName(&name,&mi);
  4598.     }
  4599.  
  4600.     RETURN(result);
  4601.     return(result);
  4602. }
  4603.  
  4604. /******************************************************************************/
  4605.  
  4606. VOID
  4607. amiga_sleep(unsigned int seconds)
  4608. {
  4609.     chkabort();
  4610.  
  4611.     ENTER();
  4612.     SHOWVALUE(seconds);
  4613.  
  4614.     if(seconds > 0)
  4615.     {
  4616.         ULONG timerSignal = (1UL << TimerPort->mp_SigBit);
  4617.         ULONG signalsReceived;
  4618.         ULONG signalsToWaitFor;
  4619.  
  4620.         TimerRequest->tr_node.io_Command    = TR_ADDREQUEST;
  4621.         TimerRequest->tr_time.tv_secs        = seconds;
  4622.         TimerRequest->tr_time.tv_micro        = 0;
  4623.  
  4624.         SetSignal(0,timerSignal);
  4625.         SendIO((struct IORequest *)TimerRequest);
  4626.  
  4627.         signalsToWaitFor = timerSignal;
  4628.         if(AllowBreak)
  4629.             signalsToWaitFor |= SIGBREAKF_CTRL_C;
  4630.  
  4631.         signalsReceived = Wait(signalsToWaitFor);
  4632.  
  4633.         /* Did we get a break signal while we were sleeping? */
  4634.         if(FLAG_IS_SET(signalsReceived,SIGBREAKF_CTRL_C))
  4635.         {
  4636.             if(CheckIO((struct IORequest *)TimerRequest) == BUSY)
  4637.                 AbortIO((struct IORequest *)TimerRequest);
  4638.  
  4639.             WaitIO((struct IORequest *)TimerRequest);
  4640.  
  4641.             /* And pull the brakes... */
  4642.             raise(SIGINT);
  4643.         }
  4644.  
  4645.         /* Proper termination. */
  4646.         if(FLAG_IS_SET(signalsReceived,timerSignal))
  4647.         {
  4648.             WaitIO((struct IORequest *)TimerRequest);
  4649.         }
  4650.     }
  4651.  
  4652.     LEAVE();
  4653. }
  4654.  
  4655. /******************************************************************************/
  4656.  
  4657. char *
  4658. amiga_crypt(char *key,char *salt)
  4659. {
  4660.     char *result;
  4661.  
  4662.     chkabort();
  4663.  
  4664.     ASSERT(key != NULL && salt != NULL);
  4665.  
  4666.     ENTER();
  4667.     SHOWSTRING(key);
  4668.     SHOWVALUE(salt);
  4669.     result = crypt(key,salt);
  4670.  
  4671.     RETURN(result);
  4672.     return(result);
  4673. }
  4674.  
  4675. /******************************************************************************/
  4676.  
  4677. char *
  4678. amiga_getpass(char *prompt)
  4679. {
  4680.     char *result;
  4681.  
  4682.     chkabort();
  4683.  
  4684.     ENTER();
  4685.     SHOWSTRING(prompt);
  4686.     result = getpass(prompt);
  4687.  
  4688.     RETURN(result);
  4689.     return(result);
  4690. }
  4691.  
  4692. /******************************************************************************/
  4693.  
  4694. int
  4695. amiga_setgid(gid_t id)
  4696. {
  4697.     int result;
  4698.  
  4699.     chkabort();
  4700.  
  4701.     ENTER();
  4702.     SHOWVALUE(id);
  4703.     result = setgid(id);
  4704.  
  4705.     RETURN(result);
  4706.     return(result);
  4707. }
  4708.  
  4709. /******************************************************************************/
  4710.  
  4711. int
  4712. amiga_setgroups(int ngroups,gid_t *groups)
  4713. {
  4714.     int result;
  4715.  
  4716.     chkabort();
  4717.  
  4718.     ASSERT(groups != NULL);
  4719.  
  4720.     ENTER();
  4721.     SHOWVALUE(ngroups);
  4722.     SHOWVALUE(groups);
  4723.  
  4724.     result = setgroups(ngroups,groups);
  4725.  
  4726.     RETURN(result);
  4727.     return(result);
  4728. }
  4729.  
  4730. /******************************************************************************/
  4731.  
  4732. gid_t
  4733. amiga_getgid(VOID)
  4734. {
  4735.     int result;
  4736.  
  4737.     chkabort();
  4738.  
  4739.     ENTER();
  4740.  
  4741.     if(RootMode)
  4742.         result = 0;
  4743.     else
  4744.         result = getgid();
  4745.  
  4746.     RETURN(result);
  4747.     return(result);
  4748. }
  4749.  
  4750. /******************************************************************************/
  4751.  
  4752. struct group *
  4753. amiga_getgrgid(gid_t gid)
  4754. {
  4755.     struct group *result;
  4756.  
  4757.     chkabort();
  4758.  
  4759.     ENTER();
  4760.     SHOWVALUE(gid);
  4761.  
  4762.     result = getgrgid(gid);
  4763.  
  4764.     RETURN(result);
  4765.     return(result);
  4766. }
  4767.  
  4768. /******************************************************************************/
  4769.  
  4770. struct group *
  4771. amiga_getgrnam(char * name)
  4772. {
  4773.     struct group *result;
  4774.  
  4775.     chkabort();
  4776.  
  4777.     ASSERT(name != NULL);
  4778.  
  4779.     ENTER();
  4780.     SHOWSTRING(name);
  4781.  
  4782.     result = getgrnam(name);
  4783.  
  4784.     RETURN(result);
  4785.     return(result);
  4786. }
  4787.  
  4788. /******************************************************************************/
  4789.  
  4790. int
  4791. amiga_getgroups(int ngroups, gid_t *groups)
  4792. {
  4793.     int result;
  4794.  
  4795.     chkabort();
  4796.  
  4797.     ASSERT(groups != NULL);
  4798.  
  4799.     ENTER();
  4800.     SHOWVALUE(ngroups);
  4801.     SHOWVALUE(groups);
  4802.  
  4803.     result = getgroups(ngroups,groups);
  4804.  
  4805.     RETURN(result);
  4806.     return(result);
  4807. }
  4808.  
  4809. /******************************************************************************/
  4810.  
  4811. struct hostent *
  4812. amiga_gethostbyaddr(char *addr, int len, int type)
  4813. {
  4814.     struct hostent *result;
  4815.  
  4816.     chkabort();
  4817.  
  4818.     ASSERT(addr != NULL);
  4819.  
  4820.     ENTER();
  4821.     SHOWVALUE(addr);
  4822.     SHOWVALUE(len);
  4823.     SHOWVALUE(type);
  4824.  
  4825.     result = gethostbyaddr(addr,len,type);
  4826.  
  4827.     RETURN(result);
  4828.     return(result);
  4829. }
  4830.  
  4831. /******************************************************************************/
  4832.  
  4833. struct hostent *
  4834. amiga_gethostbyname(char *name)
  4835. {
  4836.     struct hostent *result;
  4837.  
  4838.     chkabort();
  4839.  
  4840.     ASSERT(name != NULL);
  4841.  
  4842.     ENTER();
  4843.     SHOWSTRING(name);
  4844.  
  4845.     result = gethostbyname(name);
  4846.  
  4847.     RETURN(result);
  4848.     return(result);
  4849. }
  4850.  
  4851. /******************************************************************************/
  4852.  
  4853. struct netent *
  4854. amiga_getnetbyname(char *name)
  4855. {
  4856.     struct netent *result;
  4857.  
  4858.     chkabort();
  4859.  
  4860.     ASSERT(name != NULL);
  4861.  
  4862.     ENTER();
  4863.     SHOWSTRING(name);
  4864.  
  4865.     result = getnetbyname(name);
  4866.  
  4867.     RETURN(result);
  4868.     return(result);
  4869. }
  4870.  
  4871. /******************************************************************************/
  4872.  
  4873. int
  4874. amiga_gethostname(char *hostname,int size)
  4875. {
  4876.     int result;
  4877.  
  4878.     chkabort();
  4879.  
  4880.     ASSERT(hostname != NULL);
  4881.  
  4882.     ENTER();
  4883.     SHOWVALUE(hostname);
  4884.     SHOWVALUE(size);
  4885.  
  4886.     result = gethostname(hostname,size);
  4887.  
  4888.     if(result == 0)
  4889.         SHOWSTRING(hostname);
  4890.  
  4891.     RETURN(result);
  4892.     return(result);
  4893. }
  4894.  
  4895. /******************************************************************************/
  4896.  
  4897. struct passwd *
  4898. amiga_getpwnam(char *name)
  4899. {
  4900.     struct passwd *result;
  4901.  
  4902.     chkabort();
  4903.  
  4904.     ASSERT(name != NULL);
  4905.  
  4906.     ENTER();
  4907.     SHOWSTRING(name);
  4908.  
  4909.     result = getpwnam(name);
  4910.  
  4911.     RETURN(result);
  4912.     return(result);
  4913. }
  4914.  
  4915. /******************************************************************************/
  4916.  
  4917. struct passwd *
  4918. amiga_getpwuid(uid_t uid)
  4919. {
  4920.     struct passwd *result;
  4921.  
  4922.     chkabort();
  4923.  
  4924.     ENTER();
  4925.     SHOWVALUE(uid);
  4926.  
  4927.     result = getpwuid(uid);
  4928.  
  4929.     RETURN(result);
  4930.     return(result);
  4931. }
  4932.  
  4933. /******************************************************************************/
  4934.  
  4935. uid_t
  4936. amiga_getuid(VOID)
  4937. {
  4938.     uid_t result;
  4939.  
  4940.     chkabort();
  4941.  
  4942.     ENTER();
  4943.  
  4944.     if(RootMode)
  4945.         result = 0;
  4946.     else
  4947.         result = getuid();
  4948.  
  4949.     RETURN(result);
  4950.     return(result);
  4951. }
  4952.  
  4953. /******************************************************************************/
  4954.  
  4955. gid_t
  4956. amiga_getegid(VOID)
  4957. {
  4958.     gid_t result;
  4959.  
  4960.     chkabort();
  4961.  
  4962.     ENTER();
  4963.     result = getegid();
  4964.  
  4965.     RETURN(result);
  4966.     return(result);
  4967. }
  4968.  
  4969. /******************************************************************************/
  4970.  
  4971. uid_t
  4972. amiga_geteuid(VOID)
  4973. {
  4974.     uid_t result;
  4975.  
  4976.     chkabort();
  4977.  
  4978.     ENTER();
  4979.     result = geteuid();
  4980.  
  4981.     RETURN(result);
  4982.     return(result);
  4983. }
  4984.  
  4985. /******************************************************************************/
  4986.  
  4987. int
  4988. amiga_initgroups(char *name, gid_t basegroup)
  4989. {
  4990.     int result;
  4991.  
  4992.     chkabort();
  4993.  
  4994.     ASSERT(name != NULL);
  4995.  
  4996.     ENTER();
  4997.     SHOWSTRING(name);
  4998.     SHOWVALUE(basegroup);
  4999.  
  5000.     result = initgroups(name,basegroup);
  5001.  
  5002.     RETURN(result);
  5003.     return(result);
  5004. }
  5005.  
  5006. /******************************************************************************/
  5007.  
  5008. int
  5009. amiga_setuid(uid_t id)
  5010. {
  5011.     int result;
  5012.  
  5013.     chkabort();
  5014.  
  5015.     ENTER();
  5016.     SHOWVALUE(id);
  5017.  
  5018.     result = setuid(id);
  5019.  
  5020.     RETURN(result);
  5021.     return(result);
  5022. }
  5023.  
  5024. /******************************************************************************/
  5025.  
  5026. int
  5027. amiga_umask(int mask)
  5028. {
  5029.     int result;
  5030.  
  5031.     chkabort();
  5032.  
  5033.     ENTER();
  5034.     SHOWVALUE(mask);
  5035.  
  5036.     result = umask(mask);
  5037.  
  5038.     RETURN(result);
  5039.     return(result);
  5040. }
  5041.  
  5042. /******************************************************************************/
  5043.  
  5044. unsigned long
  5045. amiga_inet_addr(char *addr)
  5046. {
  5047.     unsigned long result;
  5048.  
  5049.     chkabort();
  5050.  
  5051.     ASSERT(addr != NULL);
  5052.  
  5053.     ENTER();
  5054.     SHOWSTRING(addr);
  5055.  
  5056.     result = inet_addr(addr);
  5057.  
  5058.     RETURN(result);
  5059.     return(result);
  5060. }
  5061.  
  5062. /******************************************************************************/
  5063.  
  5064. char *
  5065. amiga_inet_ntoa(struct in_addr in)
  5066. {
  5067.     char *result;
  5068.  
  5069.     chkabort();
  5070.  
  5071.     ENTER();
  5072.     SHOWVALUE(in.s_addr);
  5073.  
  5074.     result = Inet_NtoA(in.s_addr);
  5075.     SHOWSTRING(result);
  5076.  
  5077.     RETURN(result);
  5078.     return(result);
  5079. }
  5080.  
  5081. /******************************************************************************/
  5082.  
  5083. int    opterr = 1;
  5084. int    optind = 1;
  5085. int    optopt;
  5086. char * optarg;
  5087.  
  5088. int
  5089. amiga_getopt(int argc, char * argv[], char *opts)
  5090. {
  5091.     STATIC int sp = 1;
  5092.     int c;
  5093.     char *cp;
  5094.  
  5095.     ASSERT(argc > 0 && argv != NULL && opts != NULL);
  5096.  
  5097.     if(sp == 1)
  5098.     {
  5099.         if(optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  5100.         {
  5101.             return(EOF);
  5102.         }
  5103.         else if(strcmp(argv[optind], "--") == NULL)
  5104.         {
  5105.             optind++;
  5106.             return(EOF);
  5107.         }
  5108.     }
  5109.  
  5110.     optopt = c = argv[optind][sp];
  5111.     if(c == ':' || (cp=index(opts, c)) == NULL)
  5112.     {
  5113.         if(opterr)
  5114.             fprintf(stderr, "%s%s%c\n", argv[0], ": illegal option -- ", c);
  5115.  
  5116.         if(argv[optind][++sp] == '\0')
  5117.         {
  5118.             optind++;
  5119.             sp = 1;
  5120.         }
  5121.  
  5122.         return('?');
  5123.     }
  5124.  
  5125.     if(*++cp == ':')
  5126.     {
  5127.         if(argv[optind][sp+1] != '\0')
  5128.         {
  5129.             optarg = &argv[optind++][sp+1];
  5130.         }
  5131.         else if(++optind >= argc)
  5132.         {
  5133.             if(opterr)
  5134.                 fprintf(stderr, "%s%s%c\n", argv[0], ": option requires an argument -- ", c);
  5135.  
  5136.             sp = 1;
  5137.             return('?');
  5138.         }
  5139.         else
  5140.         {
  5141.             optarg = argv[optind++];
  5142.         }
  5143.  
  5144.         sp = 1;
  5145.     }
  5146.     else
  5147.     {
  5148.         if(argv[optind][++sp] == '\0')
  5149.         {
  5150.             sp = 1;
  5151.             optind++;
  5152.         }
  5153.  
  5154.         optarg = NULL;
  5155.     }
  5156.  
  5157.     return(c);
  5158. }
  5159.  
  5160. /******************************************************************************/
  5161.  
  5162. /* This comes from util/lib.c */
  5163. STATIC BOOL
  5164. do_match(STRPTR str, STRPTR regexp)
  5165. {
  5166.     STRPTR p;
  5167.  
  5168.     for(p = regexp; (*p) != '\0' && (*str) != '\0' ; NULL)
  5169.     {
  5170.         switch(*p)
  5171.         {
  5172.             case '?':
  5173.  
  5174.                 str++;
  5175.                 p++;
  5176.  
  5177.                 break;
  5178.  
  5179.             /* Look for a character matching the one after the '*' */
  5180.             case '*':
  5181.  
  5182.                 p++;
  5183.  
  5184.                 if((*p) == '\0')
  5185.                     return(TRUE); /* Automatic match */
  5186.  
  5187.                 while((*str) != '\0')
  5188.                 {
  5189.                     while((*str) != '\0' && ToUpper(*p) != ToUpper(*str))
  5190.                         str++;
  5191.  
  5192.                     if(do_match(str,p))
  5193.                         return(TRUE);
  5194.  
  5195.                     if((*str) == '\0')
  5196.                         return(FALSE);
  5197.                     else
  5198.                         str++;
  5199.                 }
  5200.  
  5201.                 return(FALSE);
  5202.  
  5203.             default:
  5204.  
  5205.                 if(ToUpper(*str++) != ToUpper(*p++))
  5206.                     return(FALSE);
  5207.  
  5208.                 break;
  5209.         }
  5210.     }
  5211.  
  5212.     if((*p) == '\0' && (*str) == '\0')
  5213.         return(TRUE);
  5214.  
  5215.     if((*p) == '\0' && str[0] == '.' && str[1] == '\0')
  5216.         return(TRUE);
  5217.  
  5218.     if((*str) == '\0' && (*p) == '?')
  5219.     {
  5220.         while((*p) == '?')
  5221.             p++;
  5222.  
  5223.         return((BOOL)((*p) == '\0'));
  5224.     }
  5225.  
  5226.     if((*str) == '\0' && ((*p) == '*' && p[1] == '\0'))
  5227.         return(TRUE);
  5228.  
  5229.     return(FALSE);
  5230. }
  5231.  
  5232. STATIC VOID
  5233. nstrcpy_blank(const size_t maxSize,char *to,const char *from)
  5234. {
  5235.     size_t len = 0;
  5236.  
  5237.     while((*from) != '\0' && (*from) != ' ' && len < maxSize-1)
  5238.     {
  5239.         (*to++) = (*from++);
  5240.         len++;
  5241.     }
  5242.  
  5243.     (*to) = '\0';
  5244. }
  5245.  
  5246. STATIC VOID
  5247. fill_volume_list(struct List * list)
  5248. {
  5249.     struct DosList * dol;
  5250.  
  5251.     dol = NextDosEntry(LockDosList(LDF_VOLUMES|LDF_READ),
  5252.                                    LDF_VOLUMES|LDF_READ);
  5253.     while(dol != NULL)
  5254.     {
  5255.         /* Does the volume refer to a medium that is right
  5256.          * now present in the drive?
  5257.          */
  5258.         if(dol->dol_Task != NULL)
  5259.         {
  5260.             STRPTR name = BADDR(dol->dol_Name);
  5261.             struct Node * node;
  5262.             int len;
  5263.  
  5264.             len = name[0];
  5265.  
  5266.             node = malloc(sizeof(*node) + len+1);
  5267.             if(node != NULL)
  5268.             {
  5269.                 /* Copy the name of the volume. */
  5270.                 node->ln_Name = (char *)(node + 1);
  5271.                 strncpy(node->ln_Name,&name[1],len);
  5272.                 node->ln_Name[len] = '\0';
  5273.  
  5274.                 AddTail(list,node);
  5275.             }
  5276.         }
  5277.  
  5278.         dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  5279.     }
  5280.  
  5281.     UnLockDosList(LDF_VOLUMES|LDF_READ);
  5282.  
  5283.     /* Now that we have collected all device nodes, check
  5284.      * whether the volumes are usable.
  5285.      */
  5286.     if(NOT IsListEmpty(list))
  5287.     {
  5288.         char localName[MAX_BSTR_LEN+1];
  5289.         D_S(struct InfoData,id);
  5290.         struct MsgPort * task;
  5291.         struct Node * node;
  5292.         struct Node * next;
  5293.         int len;
  5294.  
  5295.         for(node = list->lh_Head ;
  5296.             node->ln_Succ != NULL ;
  5297.             node = next)
  5298.         {
  5299.             next = node->ln_Succ;
  5300.  
  5301.             len = strlen(node->ln_Name);
  5302.             strncpy(localName,node->ln_Name,len);
  5303.             localName[len++] = ':';
  5304.             localName[len] = '\0';
  5305.  
  5306.             task = DeviceProc(localName);
  5307.             if(task == NULL || CANNOT DoPkt(task,ACTION_DISK_INFO,MKBADDR(id),    0,0,0,0))
  5308.             {
  5309.                 Remove(node);
  5310.                 free(node);
  5311.             }
  5312.         }
  5313.     }
  5314. }
  5315.  
  5316. STATIC int
  5317. deep_scan_drawer(char * drawerName,char * whichPattern,FILE * out)
  5318. {
  5319.     char * originalDrawerName;
  5320.     struct MangleInfo mi;
  5321.     int result = ERROR;
  5322.  
  5323.     originalDrawerName = drawerName;
  5324.     if(MangleName(&drawerName,&mi) == OK)
  5325.     {
  5326.         BPTR dirLock;
  5327.  
  5328.         dirLock = Lock(drawerName,SHARED_LOCK);
  5329.         if(dirLock != ZERO)
  5330.         {
  5331.             D_S(struct FileInfoBlock,fib);
  5332.  
  5333.             if(Examine(dirLock,fib))
  5334.             {
  5335.                 struct AnchorPath * ap;
  5336.  
  5337.                 ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  5338.                 if(ap != NULL)
  5339.                 {
  5340.                     BOOL stopped = FALSE;
  5341.                     BPTR oldDir;
  5342.                     LONG error;
  5343.  
  5344.                     oldDir = CurrentDir(dirLock);
  5345.  
  5346.                     memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  5347.  
  5348.                     ap->ap_Strlen        = MAX_FILENAME_LEN;
  5349.                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  5350.  
  5351.                     if((error = MatchFirst("",ap)) == OK)
  5352.                     {
  5353.                         BOOL check;
  5354.  
  5355.                         do
  5356.                         {
  5357.                             D(("checking |%s|",ap->ap_Buf));
  5358.  
  5359.                             check = TRUE;
  5360.  
  5361.                             if(FIB_IS_FILE(&ap->ap_Info))
  5362.                             {
  5363.                                 SHOWMSG("this is a file");
  5364.                             }
  5365.                             else
  5366.                             {
  5367.                                 SHOWMSG("this is a drawer");
  5368.  
  5369.                                 if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  5370.                                 {
  5371.                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  5372.                                 }
  5373.                                 else
  5374.                                 {
  5375.                                     CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  5376.                                     check = FALSE;
  5377.                                 }
  5378.                             }
  5379.  
  5380.                             if(check)
  5381.                             {
  5382.                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  5383.  
  5384.                                 if(do_match(ap->ap_Info.fib_FileName,whichPattern))
  5385.                                 {
  5386.                                     D(("Output |%s/%s|",originalDrawerName,ap->ap_Buf));
  5387.                                     if(fprintf(out,"%s/%s\n",originalDrawerName,ap->ap_Buf) < 0)
  5388.                                     {
  5389.                                         stopped = TRUE;
  5390.                                         break;
  5391.                                     }
  5392.                                 }
  5393.                                 else
  5394.                                 {
  5395.                                     SHOWMSG("but its name does not match");
  5396.                                 }
  5397.                             }
  5398.                         }
  5399.                         while((error = MatchNext(ap)) == OK);
  5400.                     }
  5401.  
  5402.                     MatchEnd(ap);
  5403.  
  5404.                     CurrentDir(oldDir);
  5405.  
  5406.                     if(NOT stopped)
  5407.                     {
  5408.                         if(error == ERROR_NO_MORE_ENTRIES)
  5409.                         {
  5410.                             result = OK;
  5411.                         }
  5412.                         else if(error == ERROR_BREAK)
  5413.                         {
  5414.                             /* Don't do anything; we are going
  5415.                              * to delete the file anyway.
  5416.                              */
  5417.                         }
  5418.                         else
  5419.                         {
  5420.                             SetIoErr(error);
  5421.                             MapIoErrToErrno();
  5422.                         }
  5423.                     }
  5424.  
  5425.                     free(ap);
  5426.                 }
  5427.                 else
  5428.                 {
  5429.                     errno = ENOMEM;
  5430.                 }
  5431.             }
  5432.             else
  5433.             {
  5434.                 MapIoErrToErrno();
  5435.             }
  5436.  
  5437.             UnLock(dirLock);
  5438.         }
  5439.         else
  5440.         {
  5441.             MapIoErrToErrno();
  5442.         }
  5443.  
  5444.         UnmangleName(&drawerName,&mi);
  5445.     }
  5446.  
  5447.     return(result);
  5448. }
  5449.  
  5450. int
  5451. amiga_system(char *cmd)
  5452. {
  5453.     char redirectionFileBuffer[MAX_FILENAME_LEN];
  5454.     char *redirectionFile = redirectionFileBuffer;
  5455.     struct MangleInfo mi;
  5456.     int result = ERROR;
  5457.     char *stop;
  5458.     char *options;
  5459.     char *cmdName;
  5460.     int cmdLen,i;
  5461.     int quoteCount;
  5462.  
  5463.     chkabort();
  5464.  
  5465.     ASSERT(cmd != NULL);
  5466.  
  5467.     ENTER();
  5468.     SHOWSTRING(cmd);
  5469.  
  5470.     /* Handle two special cases for the smb client program,
  5471.      * which for reasons unknown to me resorts to calling
  5472.      * the Unix "ls" and "find" programs to collect lists
  5473.      * of files.
  5474.      *
  5475.      * The commands to watch for take the following forms:
  5476.      *
  5477.      *    /bin/ls file_to_list > output_filename
  5478.      *    find directory_to_list -name "pattern_to_list" -print > output_filename
  5479.      */
  5480.     stop = cmd;
  5481.     while((*stop) != ' ' && (*stop) != '\0')
  5482.         stop++;
  5483.  
  5484.     /* This will point behind the command name,
  5485.      * to the beginning of the list of options,
  5486.      * if any.
  5487.      */
  5488.     options = stop;
  5489.     while((*options) == ' ')
  5490.         options++;
  5491.  
  5492.     /* Now go and isolate the command name. */
  5493.     cmdName = cmd;
  5494.     cmdLen = stop-cmd;
  5495.     for(i = cmdLen - 1 ; i >= 0 ; i--)
  5496.     {
  5497.         if(cmd[i] == '/' || cmd[i] == ':')
  5498.         {
  5499.             cmdName = &cmd[i+1];
  5500.  
  5501.             stop = cmdName;
  5502.             while((*stop) != ' ' && (*stop) != '\0')
  5503.                 stop++;
  5504.  
  5505.             cmdLen = stop-cmdName;
  5506.  
  5507.             break;
  5508.         }
  5509.     }
  5510.  
  5511.     /* We have isolated the command name, now
  5512.      * find the redirection file name.
  5513.      */
  5514.     quoteCount = 0;
  5515.     strcpy(redirectionFile,"");
  5516.     for(i = 0 ; i < strlen(cmd) ; i++)
  5517.     {
  5518.         if(cmd[i] == '\"')
  5519.             quoteCount = (1-quoteCount);
  5520.  
  5521.         if(cmd[i] == '>' && quoteCount == 0)
  5522.         {
  5523.             char * from;
  5524.  
  5525.             from = &cmd[i+1];
  5526.             while((*from) == ' ')
  5527.                 from++;
  5528.  
  5529.             /* Note that we rely upon the
  5530.              * redirection file name not to contain
  5531.              * quote or escape characters.
  5532.              */
  5533.             nstrcpy_blank(sizeof(redirectionFileBuffer),redirectionFile,from);
  5534.             break;
  5535.         }
  5536.     }
  5537.  
  5538.     /* Now check which command we got. */
  5539.     if(cmdLen == 2 && Strnicmp(cmdName,"ls",2) == SAME)
  5540.     {
  5541.         char localDirName[MAX_FILENAME_LEN];
  5542.         char * dirName;
  5543.  
  5544.         dirName = ".";
  5545.  
  5546.         if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  5547.         {
  5548.             char whichPatternBuffer[MAX_FILENAME_LEN];
  5549.             char *whichPattern = whichPatternBuffer;
  5550.             BOOL oldAllowBreak = AllowBreak;
  5551.  
  5552.             /* We don't want to be interrupted. */
  5553.             AllowBreak = FALSE;
  5554.  
  5555.             /* Now find the pattern to use. */
  5556.             nstrcpy_blank(sizeof(whichPatternBuffer),whichPattern,options);
  5557.  
  5558.             SHOWMSG("doing `ls'");
  5559.             SHOWSTRING(whichPattern);
  5560.             SHOWSTRING(redirectionFile);
  5561.  
  5562.             /* What happens next is that the contents of the
  5563.              * current directory are scanned. All names
  5564.              * that match the given pattern are stored in the
  5565.              * redirection file.
  5566.              */
  5567.  
  5568.             if(MangleName(&redirectionFile,&mi) == OK)
  5569.             {
  5570.                 FILE * out;
  5571.  
  5572.                 ForbidDOS();
  5573.  
  5574.                 out = fopen(redirectionFile,"wb");
  5575.                 if(out != NULL)
  5576.                 {
  5577.                     SHOWSTRING(localDirName);
  5578.  
  5579.                     if(strcmp(localDirName,"/") == SAME)
  5580.                     {
  5581.                         struct List list;
  5582.                         struct Node * node;
  5583.  
  5584.                         SHOWMSG("listing volumes");
  5585.  
  5586.                         NewList(&list);
  5587.                         fill_volume_list(&list);
  5588.  
  5589.                         while((node = RemHead(&list)) != NULL)
  5590.                         {
  5591.                             D(("checking '%s'",node->ln_Name));
  5592.  
  5593.                             if(do_match(node->ln_Name,whichPattern))
  5594.                             {
  5595.                                 SHOWMSG(">>> matches");
  5596.  
  5597.                                 if(fprintf(out,"%s\n",node->ln_Name) < 0)
  5598.                                     break;
  5599.                             }
  5600.                             else
  5601.                             {
  5602.                                 SHOWMSG(">>> does not match");
  5603.                             }
  5604.  
  5605.                             free(node);
  5606.                         }
  5607.  
  5608.                         while((node = RemHead(&list)) != NULL)
  5609.                             free(node);
  5610.                     }
  5611.                     else
  5612.                     {
  5613.                         BPTR dirLock;
  5614.  
  5615.                         SHOWMSG("listing drawers");
  5616.  
  5617.                         dirLock = Lock("",SHARED_LOCK);
  5618.                         if(dirLock != ZERO)
  5619.                         {
  5620.                             D_S(struct FileInfoBlock,fib);
  5621.  
  5622.                             if(Examine(dirLock,fib))
  5623.                             {
  5624.                                 BOOL stopped = FALSE;
  5625.  
  5626.                                 while(ExNext(dirLock,fib))
  5627.                                 {
  5628.                                     D(("checking '%s'",fib->fib_FileName));
  5629.  
  5630.                                     if(do_match(fib->fib_FileName,whichPattern))
  5631.                                     {
  5632.                                         SHOWMSG(">>> matches");
  5633.  
  5634.                                         if(fprintf(out,"%s\n",fib->fib_FileName) < 0)
  5635.                                         {
  5636.                                             stopped = TRUE;
  5637.                                             break;
  5638.                                         }
  5639.                                     }
  5640.                                     else
  5641.                                     {
  5642.                                         SHOWMSG(">>> does not match");
  5643.                                     }
  5644.                                 }
  5645.  
  5646.                                 if(NOT stopped)
  5647.                                 {
  5648.                                     LONG error = IoErr();
  5649.  
  5650.                                     if(error == ERROR_NO_MORE_ENTRIES)
  5651.                                     {
  5652.                                         result = OK;
  5653.                                     }
  5654.                                     else
  5655.                                     {
  5656.                                         SetIoErr(error);
  5657.                                         MapIoErrToErrno();
  5658.                                     }
  5659.                                 }
  5660.                             }
  5661.                             else
  5662.                             {
  5663.                                 MapIoErrToErrno();
  5664.                             }
  5665.  
  5666.                             UnLock(dirLock);
  5667.                         }
  5668.                         else
  5669.                         {
  5670.                             MapIoErrToErrno();
  5671.                         }
  5672.                     }
  5673.  
  5674.                     fclose(out);
  5675.  
  5676.                     if(result != OK)
  5677.                         DeleteFile(redirectionFile);
  5678.                 }
  5679.  
  5680.                 PermitDOS();
  5681.  
  5682.                 UnmangleName(&cmd,&mi);
  5683.             }
  5684.  
  5685.             AllowBreak = oldAllowBreak;
  5686.         }
  5687.     }
  5688.     else if (cmdLen == 4 && Strnicmp(cmdName,"find",4) == SAME)
  5689.     {
  5690.         char whichDrawerBuffer[MAX_FILENAME_LEN];
  5691.         char * whichDrawer = whichDrawerBuffer;
  5692.         char whichPattern[MAX_FILENAME_LEN];
  5693.         const int _nameLen = strlen("-name");
  5694.         BOOL oldAllowBreak = AllowBreak;
  5695.         struct Node * node;
  5696.  
  5697.         /* We don't want to be interrupted. */
  5698.         AllowBreak = FALSE;
  5699.  
  5700.         /* Now find the drawer to examine. */
  5701.         nstrcpy_blank(sizeof(whichDrawerBuffer),whichDrawer,options);
  5702.  
  5703.         /* Find the pattern to search for. */
  5704.         strcpy(whichPattern,"");
  5705.         for(i = 0 ; i < strlen(options) ; i++)
  5706.         {
  5707.             if(Strnicmp(&options[i],"-name",_nameLen) == SAME)
  5708.             {
  5709.                 const int maxLen = sizeof(whichPattern)-1;
  5710.                 int whichPatternLen;
  5711.                 int escapeCount;
  5712.                 int quoteCount;
  5713.                 char * from;
  5714.                 char * to;
  5715.  
  5716.                 /* `from' should now point straight at the
  5717.                  * search pattern, which is probably enclosed
  5718.                  * in quote characters.
  5719.                  */
  5720.                 from = &options[i+_nameLen];
  5721.                 while((*from) == ' ')
  5722.                     from++;
  5723.  
  5724.                 to = whichPattern;
  5725.                 whichPatternLen = 0;
  5726.                 quoteCount = 0;
  5727.                 escapeCount = 0;
  5728.                 while((*from) != '\0' && whichPatternLen < maxLen)
  5729.                 {
  5730.                     if(escapeCount != 0)
  5731.                     {
  5732.                         (*to++) = (*from++);
  5733.                         whichPatternLen++;
  5734.                         escapeCount = 0;
  5735.                     }
  5736.                     else if((*from) == '\\')
  5737.                     {
  5738.                         escapeCount = (1-escapeCount);
  5739.                         from++;
  5740.                     }
  5741.                     else if ((*from) == '\"')
  5742.                     {
  5743.                         quoteCount = (1-quoteCount);
  5744.                         from++;
  5745.                     }
  5746.                     else
  5747.                     {
  5748.                         if((*from) == ' ' && quoteCount == 0)
  5749.                         {
  5750.                             break;
  5751.                         }
  5752.                         else
  5753.                         {
  5754.                             (*to++) = (*from++);
  5755.                             whichPatternLen++;
  5756.                         }
  5757.                     }
  5758.                 }
  5759.  
  5760.                 (*to) = '\0';
  5761.             }
  5762.         }
  5763.  
  5764.         SHOWMSG("doing `find'");
  5765.         SHOWSTRING(whichDrawer);
  5766.         SHOWSTRING(whichPattern);
  5767.         SHOWSTRING(redirectionFile);
  5768.  
  5769.         /* Things are a little bit more complicated here. The
  5770.          * "find" program scans recursively through a directory
  5771.          * tree. We emulate this behaviour by having the MatchFirst/MatchNext
  5772.          * routines iterate through the directory tree. The
  5773.          * name of every file found is matched against the given
  5774.          * pattern and, if necessary, written to the redirection
  5775.          * file. Note that matching is performed only on the
  5776.          * file name, not on the entire path.
  5777.          */
  5778.  
  5779.         if(MangleName(&redirectionFile,&mi) == OK)
  5780.         {
  5781.             FILE * out;
  5782.  
  5783.             ForbidDOS();
  5784.  
  5785.             out = fopen(redirectionFile,"wb");
  5786.             if(out != NULL)
  5787.             {
  5788.                 char localDirName[MAX_FILENAME_LEN];
  5789.                 char * dirName;
  5790.  
  5791.                 dirName = whichDrawer;
  5792.  
  5793.                 if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  5794.                 {
  5795.                     D(("listing path '%s'",dirName));
  5796.  
  5797.                     if(strcmp(dirName,"/") == SAME)
  5798.                     {
  5799.                         struct List list;
  5800.  
  5801.                         SHOWMSG("checking all 'drawers' in the fake root");
  5802.  
  5803.                         NewList(&list);
  5804.                         fill_volume_list(&list);
  5805.  
  5806.                         while((node = RemHead(&list)) != NULL)
  5807.                         {
  5808.                             strcpy(localDirName,"/");
  5809.                             strcat(localDirName,node->ln_Name);
  5810.                             free(node);
  5811.  
  5812.                             D(("checking '%s'",localDirName));
  5813.  
  5814.                             result = deep_scan_drawer(localDirName,whichPattern,out);
  5815.                             if(result != OK)
  5816.                                 break;
  5817.                         }
  5818.  
  5819.                         while((node = RemHead(&list)) != NULL)
  5820.                             free(node);
  5821.                     }
  5822.                     else
  5823.                     {
  5824.                         SHOWMSG("checking only a local drawer");
  5825.  
  5826.                         result = deep_scan_drawer(dirName,whichPattern,out);
  5827.                     }
  5828.                 }
  5829.  
  5830.                 fclose(out);
  5831.  
  5832.                 if(result != OK)
  5833.                     DeleteFile(redirectionFile);
  5834.             }
  5835.  
  5836.             PermitDOS();
  5837.  
  5838.             UnmangleName(&cmd,&mi);
  5839.         }
  5840.  
  5841.         AllowBreak = oldAllowBreak;
  5842.     }
  5843.     else
  5844.     {
  5845.         if(MangleName(&cmd,&mi) == OK)
  5846.         {
  5847.             ForbidDOS();
  5848.             result = system(cmd);
  5849.             PermitDOS();
  5850.  
  5851.             UnmangleName(&cmd,&mi);
  5852.         }
  5853.     }
  5854.  
  5855.     RETURN(result);
  5856.     return(result);
  5857. }
  5858.  
  5859. /******************************************************************************/
  5860.  
  5861. int
  5862. amiga_fork(VOID)    /* dummy */
  5863. {
  5864.     int result;
  5865.  
  5866.     chkabort();
  5867.  
  5868.     ENTER();
  5869.  
  5870.     result = ERROR;
  5871.     errno = ENOSYS;
  5872.  
  5873.     RETURN(result);
  5874.     return(result);
  5875. }
  5876.  
  5877. /******************************************************************************/
  5878.  
  5879. STATIC BOOL
  5880. SetFileSocket(FILE *stream,int sockfd)
  5881. {
  5882.     struct UFB * ufb;
  5883.     BOOL success = FALSE;
  5884.  
  5885.     ASSERT(stream != NULL);
  5886.  
  5887.     ENTER();
  5888.  
  5889.     /* Check which buffer the file
  5890.      * is attached to.
  5891.      */
  5892.     ufb = chkufb(fileno(stream));
  5893.     if(ufb != NULL)
  5894.     {
  5895.         SHOWVALUE(ufb);
  5896.  
  5897.         /* Save the file handle. */
  5898.         if(SaveDescriptor(ufb))
  5899.         {
  5900.             /* And put the socket in its place. */
  5901.             ufb->ufbfh = sockfd;
  5902.             SET_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  5903.  
  5904.             success = TRUE;
  5905.         }
  5906.     }
  5907.     else
  5908.     {
  5909.         SHOWMSG("no ufb");
  5910.     }
  5911.  
  5912.     RETURN(success);
  5913.     return(success);
  5914. }
  5915.  
  5916. STATIC VOID
  5917. DaemonInit(VOID)
  5918. {
  5919.     struct DaemonMessage * dm;
  5920.     int sock;
  5921.  
  5922.     ENTER();
  5923.  
  5924.     /* This routine is called when the program starts up.
  5925.      * If it was launched by the INet super server, this
  5926.      * program will run as a daemon. We pick up its
  5927.      * socket input stream and attach it to our stdio
  5928.      * streams.
  5929.      */
  5930.     dm = (struct DaemonMessage *)((struct Process *)FindTask(NULL))->pr_ExitData;
  5931.     if(dm != NULL)
  5932.     {
  5933.         sock = ObtainSocket(dm->dm_ID,dm->dm_Family,dm->dm_Type,0);
  5934.         if(sock != -1)
  5935.         {
  5936.             BOOL success = FALSE;
  5937.             int sock_stdin;
  5938.             int sock_stdout;
  5939.             int sock_stderr;
  5940.  
  5941.             sock_stdin    = Dup2Socket(sock,-1);
  5942.             sock_stdout    = Dup2Socket(sock,-1);
  5943.             sock_stderr    = Dup2Socket(sock,-1);
  5944.  
  5945.             if(sock_stdin != -1 && sock_stdout != -1 && sock_stderr != -1)
  5946.             {
  5947.                 SHOWMSG("got all sockets");
  5948.  
  5949.                 D(("stdin  = sock %ld",sock_stdin));
  5950.                 D(("stdout = sock %ld",sock_stdout));
  5951.                 D(("stderr = sock %ld",sock_stderr));
  5952.  
  5953.                 if(SetFileSocket(stdin,sock_stdin) &&
  5954.                    SetFileSocket(stdout,sock_stdout) &&
  5955.                    SetFileSocket(stderr,sock_stderr))
  5956.                 {
  5957.                     SHOWMSG("and all streams are initialized");
  5958.  
  5959.                     success = TRUE;
  5960.                 }
  5961.                 else
  5962.                 {
  5963.                     SHOWMSG("failed to initialize streams");
  5964.                 }
  5965.             }
  5966.             else
  5967.             {
  5968.                 SHOWMSG("didn't get the sockets");
  5969.             }
  5970.  
  5971.             if(NO success)
  5972.             {
  5973.                 if(sock_stdin != -1)
  5974.                     CloseSocket(sock_stdin);
  5975.  
  5976.                 if(sock_stdout != -1)
  5977.                     CloseSocket(sock_stdout);
  5978.  
  5979.                 if(sock_stderr != -1)
  5980.                     CloseSocket(sock_stderr);
  5981.             }
  5982.         }
  5983.         else
  5984.         {
  5985.             SHOWMSG("no socket");
  5986.         }
  5987.     }
  5988.     else
  5989.     {
  5990.         SHOWMSG("No daemon message");
  5991.     }
  5992.  
  5993.     LEAVE();
  5994. }
  5995.  
  5996. /******************************************************************************/
  5997.  
  5998. VOID
  5999. __tzset(VOID)
  6000. {
  6001.     STATIC char TimeZoneName[20] = "";
  6002.  
  6003.     /* This routine sets up the internal
  6004.      * time zone variable according to
  6005.      * the local settings.
  6006.      */
  6007.     if(STRING_IS_EMPTY(TimeZoneName))
  6008.     {
  6009.         int hoursWest = MinutesWest / 60;
  6010.  
  6011.         if(hoursWest >= 0)
  6012.             sprintf(TimeZoneName,"GMT+%02d", hoursWest);
  6013.         else
  6014.             sprintf(TimeZoneName,"GMT-%02d",-hoursWest);
  6015.     }
  6016.  
  6017.     _TZ = TimeZoneName;
  6018. }
  6019.  
  6020. /******************************************************************************/
  6021.  
  6022. time_t
  6023. time(time_t *timeptr)
  6024. {
  6025.     time_t currentTime;
  6026.     struct timeval tv;
  6027.  
  6028.     chkabort();
  6029.  
  6030.     GetSysTime((APTR)&tv);
  6031.  
  6032.     currentTime = UNIX_TIME_OFFSET + tv.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  6033.  
  6034.     if(timeptr != NULL)
  6035.         (*timeptr) = currentTime;
  6036.  
  6037.     return(currentTime);
  6038. }
  6039.  
  6040. /******************************************************************************/
  6041.  
  6042. STATIC struct tm *
  6043. ConvertTime(ULONG seconds)
  6044. {
  6045.     STATIC struct tm tm;
  6046.     struct ClockData clockData;
  6047.     ULONG delta;
  6048.  
  6049.     chkabort();
  6050.  
  6051.     Amiga2Date(seconds,&clockData);
  6052.  
  6053.     tm.tm_sec    = clockData.sec;
  6054.     tm.tm_min    = clockData.min;
  6055.     tm.tm_hour    = clockData.hour;
  6056.     tm.tm_mday    = clockData.mday;
  6057.     tm.tm_mon    = clockData.month - 1;
  6058.     tm.tm_year    = clockData.year - 1900;
  6059.     tm.tm_wday    = clockData.wday;
  6060.     tm.tm_isdst    = 0;
  6061.  
  6062.     clockData.mday    = 1;
  6063.     clockData.month    = 1;
  6064.  
  6065.     delta = Date2Amiga(&clockData);
  6066.  
  6067.     tm.tm_yday = (seconds - delta) / (24*60*60);
  6068.  
  6069.     return(&tm);
  6070. }
  6071.  
  6072. struct tm *
  6073. gmtime(const time_t *t)
  6074. {
  6075.     struct tm * result;
  6076.     ULONG seconds;
  6077.  
  6078.     if((*t) < UNIX_TIME_OFFSET)
  6079.         seconds = 0;
  6080.     else
  6081.         seconds = (*t) - UNIX_TIME_OFFSET;
  6082.  
  6083.     result = ConvertTime(seconds);
  6084.  
  6085.     return(result);
  6086. }
  6087.  
  6088. struct tm *
  6089. localtime(const time_t *t)
  6090. {
  6091.     struct tm * result;
  6092.     ULONG seconds;
  6093.  
  6094.     if((*t) < (UNIX_TIME_OFFSET + 60*MinutesWest))
  6095.         seconds = 0;
  6096.     else
  6097.         seconds = (*t) - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  6098.  
  6099.     result = ConvertTime(seconds);
  6100.  
  6101.     return(result);
  6102. }
  6103.  
  6104. /******************************************************************************/
  6105.  
  6106. int
  6107. amiga_strcasecmp(char *a,char *b)
  6108. {
  6109.     int result;
  6110.  
  6111.     ASSERT(a != NULL && b != NULL);
  6112.  
  6113.     result = Stricmp((STRPTR)a,b);
  6114.  
  6115.     return(result);
  6116. }
  6117.  
  6118. int
  6119. amiga_strncasecmp(char *a,char *b,int len)
  6120. {
  6121.     int result;
  6122.  
  6123.     ASSERT(a != NULL && b != NULL);
  6124.  
  6125.     result = Strnicmp(a,b,len);
  6126.  
  6127.     return(result);
  6128. }
  6129.  
  6130. /******************************************************************************/
  6131.  
  6132. VOID
  6133. (*amiga_signal(int which,VOID (* action)(int)))(int)
  6134. {
  6135.     VOID (* result)(int);
  6136.  
  6137.     chkabort();
  6138.  
  6139.     ENTER();
  6140.  
  6141.     if(SIGABRT <= which && which <= SIGTERM)
  6142.         result = signal(which,action);
  6143.     else
  6144.         result = SIG_DFL;
  6145.  
  6146.     RETURN(result);
  6147.     return(result);
  6148. }
  6149.  
  6150. /******************************************************************************/
  6151.  
  6152. VOID
  6153. amiga_alarm(int seconds)    /* dummy */
  6154. {
  6155.     chkabort();
  6156.  
  6157.     ENTER();
  6158.  
  6159.     LEAVE();
  6160. }
  6161.  
  6162. /******************************************************************************/
  6163.  
  6164. int
  6165. amiga_waitpid(pid_t pid,int *status,int options)    /* dummy */
  6166. {
  6167.     int result;
  6168.  
  6169.     chkabort();
  6170.  
  6171.     ENTER();
  6172.  
  6173.     result = ERROR;
  6174.     errno = ENOSYS;
  6175.  
  6176.     RETURN(result);
  6177.     return(result);
  6178. }
  6179.  
  6180. /******************************************************************************/
  6181.  
  6182. long
  6183. amiga_setsid(VOID)
  6184. {
  6185.     long result;
  6186.  
  6187.     chkabort();
  6188.  
  6189.     ENTER();
  6190.  
  6191.     result = (long)setsid();
  6192.  
  6193.     RETURN(result);
  6194.     return(result);
  6195. }
  6196.  
  6197. /******************************************************************************/
  6198.  
  6199. int
  6200. amiga_setreuid(uid_t real, uid_t eff)
  6201. {
  6202.     int result;
  6203.  
  6204.     chkabort();
  6205.  
  6206.     ENTER();
  6207.  
  6208.     result = setreuid(real,eff);
  6209.  
  6210.     RETURN(result);
  6211.     return(result);
  6212. }
  6213.  
  6214. /******************************************************************************/
  6215.  
  6216. int
  6217. amiga_setregid(gid_t real, gid_t eff)
  6218. {
  6219.     int result;
  6220.  
  6221.     chkabort();
  6222.  
  6223.     ENTER();
  6224.  
  6225.     result = setregid(real,eff);
  6226.  
  6227.     RETURN(result);
  6228.     return(result);
  6229. }
  6230.  
  6231. /******************************************************************************/
  6232.  
  6233. int
  6234. amiga_getsockname(int sockfd,struct sockaddr *name,int *namelen)
  6235. {
  6236.     struct UFB * ufb;
  6237.     int result = ERROR;
  6238.  
  6239.     chkabort();
  6240.  
  6241.     ASSERT(name != NULL && namelen != NULL);
  6242.  
  6243.     ENTER();
  6244.  
  6245.     ufb = chkufb(sockfd);
  6246.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  6247.         result = getsockname(ufb->ufbfh,name,(LONG *)namelen);
  6248.     else
  6249.         errno = ENOTSOCK;
  6250.  
  6251.     RETURN(result);
  6252.     return(result);
  6253. }
  6254.  
  6255. /******************************************************************************/
  6256.  
  6257. int
  6258. amiga_statfs(char *name,struct statfs *f)
  6259. {
  6260.     char localName[MAX_FILENAME_LEN];
  6261.     int result = ERROR;
  6262.  
  6263.     chkabort();
  6264.  
  6265.     ASSERT(name != NULL && f != NULL);
  6266.  
  6267.     ENTER();
  6268.  
  6269.     SHOWSTRING(name);
  6270.     SHOWVALUE(f);
  6271.  
  6272.     if(TranslateRelativePath(&name,localName,sizeof(localName)) == OK)
  6273.     {
  6274.         /* Make up something for the virtual root directory. */
  6275.         if(strcmp(name,"/") == SAME)
  6276.         {
  6277.             memset(f,0,sizeof(*f));
  6278.  
  6279.             f->f_fsize = 512;
  6280.  
  6281.             /* Try to reuse the data from our last scan. */
  6282.             if(RootBlocks > 0 && RootBlocksUsed > 0)
  6283.             {
  6284.                 f->f_blocks    = RootBlocks;
  6285.                 f->f_bfree    = RootBlocks - RootBlocksUsed;
  6286.             }
  6287.             else
  6288.             {
  6289.                 f->f_blocks    = 0x7FFFFFFF/f->f_fsize;
  6290.                 f->f_bfree    = f->f_blocks - 1;
  6291.             }
  6292.  
  6293.             f->f_bsize    = f->f_fsize;
  6294.             f->f_bavail    = f->f_bfree;
  6295.  
  6296.             SHOWVALUE(f->f_fsize);
  6297.             SHOWVALUE(f->f_bsize);
  6298.             SHOWVALUE(f->f_blocks);
  6299.             SHOWVALUE(f->f_bfree);
  6300.             SHOWVALUE(f->f_bavail);
  6301.  
  6302.             result = OK;
  6303.         }
  6304.         else
  6305.         {
  6306.             struct MangleInfo mi;
  6307.             BPTR fileLock;
  6308.  
  6309.             if(MangleName(&name,&mi) == OK)
  6310.             {
  6311.                 ForbidDOS();
  6312.  
  6313.                 fileLock = Lock(name,SHARED_LOCK);
  6314.                 if(fileLock != ZERO)
  6315.                 {
  6316.                     D_S(struct InfoData,id);
  6317.  
  6318.                     if(Info(fileLock,id))
  6319.                     {
  6320.                         memset(f,0,sizeof(*f));
  6321.  
  6322.                         /* Make sure that these never drop to zero. */
  6323.                         if(id->id_NumBlocks == 0)
  6324.                             id->id_NumBlocks = 1;
  6325.  
  6326.                         if(id->id_BytesPerBlock == 0)
  6327.                             id->id_BytesPerBlock = 512;
  6328.  
  6329.                         f->f_fsize    = id->id_BytesPerBlock;                        /* fundamental file system block size */
  6330.                         f->f_blocks    = id->id_NumBlocks;                            /* total data blocks in file system */
  6331.                         f->f_bfree    = id->id_NumBlocks - id->id_NumBlocksUsed;    /* free blocks in fs */
  6332.                         f->f_bsize    = f->f_fsize;                                /* optimal transfer block size */
  6333.                         f->f_bavail    = f->f_bfree;                                /* free blocks avail to non-superuser */
  6334.  
  6335.                         SHOWVALUE(f->f_fsize);
  6336.                         SHOWVALUE(f->f_bsize);
  6337.                         SHOWVALUE(f->f_blocks);
  6338.                         SHOWVALUE(f->f_bfree);
  6339.                         SHOWVALUE(f->f_bavail);
  6340.  
  6341.                         result = OK;
  6342.                     }
  6343.                     else
  6344.                     {
  6345.                         MapIoErrToErrno();
  6346.                     }
  6347.  
  6348.                     UnLock(fileLock);
  6349.                 }
  6350.                 else
  6351.                 {
  6352.                     MapIoErrToErrno();
  6353.                 }
  6354.  
  6355.                 PermitDOS();
  6356.  
  6357.                 UnmangleName(&name,&mi);
  6358.             }
  6359.         }
  6360.     }
  6361.  
  6362.     RETURN(result);
  6363.     return(result);
  6364. }
  6365.  
  6366. /******************************************************************************/
  6367.  
  6368. int
  6369. amiga_execl(char *path,char *arg,...)    /* dummy */
  6370. {
  6371.     int result;
  6372.  
  6373.     chkabort();
  6374.  
  6375.     ENTER();
  6376.  
  6377.     result = ERROR;
  6378.     errno = ENOSYS;
  6379.  
  6380.     RETURN(result);
  6381.     return(result);
  6382. }
  6383.  
  6384. /******************************************************************************/
  6385.  
  6386. char *
  6387. amiga_strerror(int error)
  6388. {
  6389.     struct TagItem tags[2];
  6390.     char *result;
  6391.  
  6392.     chkabort();
  6393.  
  6394.     ENTER();
  6395.  
  6396.     tags[0].ti_Tag    = SBTM_GETVAL(SBTC_ERRNOSTRPTR);
  6397.     tags[0].ti_Data    = error;
  6398.     tags[1].ti_Tag    = TAG_END;
  6399.  
  6400.     SocketBaseTagList(tags);
  6401.  
  6402.     result = (char *)tags[0].ti_Data;
  6403.  
  6404.     RETURN(result);
  6405.     return(result);
  6406. }
  6407.  
  6408. /******************************************************************************/
  6409.  
  6410. int
  6411. amiga_access(char *name,int modes)
  6412. {
  6413.     struct MangleInfo mi;
  6414.     int result = ERROR;
  6415.  
  6416.     chkabort();
  6417.  
  6418.     ASSERT(name != NULL);
  6419.  
  6420.     ENTER();
  6421.  
  6422.     if(MangleName(&name,&mi) == OK)
  6423.     {
  6424.         ForbidDOS();
  6425.         result = access(name,modes);
  6426.         PermitDOS();
  6427.  
  6428.         UnmangleName(&name,&mi);
  6429.     }
  6430.  
  6431.     RETURN(result);
  6432.     return(result);
  6433. }
  6434.  
  6435. /******************************************************************************/
  6436.  
  6437. STATIC VOID
  6438. MapIoErrToErrno(VOID)
  6439. {
  6440.     /* This routine maps AmigaDOS error codes to
  6441.      * Unix error codes, as far as this is possible.
  6442.      * This table contains AmigaDOS error codes
  6443.      * the emulated routines won't generate. I have
  6444.      * included them for the sake of completeness.
  6445.      */
  6446.     struct { LONG IoErr; LONG errno; } MapTable[] =
  6447.     {
  6448.         ERROR_NO_FREE_STORE,            ENOMEM,
  6449.         ERROR_TASK_TABLE_FULL,            ENOMEM,
  6450.         ERROR_BAD_TEMPLATE,                EINVAL,
  6451.         ERROR_BAD_NUMBER,                EINVAL,
  6452.         ERROR_REQUIRED_ARG_MISSING,        EINVAL,
  6453.         ERROR_KEY_NEEDS_ARG,            EINVAL,
  6454.         ERROR_TOO_MANY_ARGS,            EINVAL,
  6455.         ERROR_UNMATCHED_QUOTES,            EINVAL,
  6456.         ERROR_LINE_TOO_LONG,            ENAMETOOLONG,
  6457.         ERROR_FILE_NOT_OBJECT,            ENOEXEC,
  6458.         ERROR_INVALID_RESIDENT_LIBRARY,    EIO,
  6459.         ERROR_NO_DEFAULT_DIR,            EIO,
  6460.         ERROR_OBJECT_IN_USE,            EBUSY,
  6461.         ERROR_OBJECT_EXISTS,            EBUSY,
  6462.         ERROR_DIR_NOT_FOUND,            ENOENT,
  6463.         ERROR_OBJECT_NOT_FOUND,            ENOENT,
  6464.         ERROR_BAD_STREAM_NAME,            EINVAL,
  6465.         ERROR_OBJECT_TOO_LARGE,            EFBIG,
  6466.         ERROR_ACTION_NOT_KNOWN,            ENOSYS,
  6467.         ERROR_INVALID_COMPONENT_NAME,    EINVAL,
  6468.         ERROR_INVALID_LOCK,                EBADF,
  6469.         ERROR_OBJECT_WRONG_TYPE,        EFTYPE,
  6470.         ERROR_DISK_NOT_VALIDATED,        EROFS,
  6471.         ERROR_DISK_WRITE_PROTECTED,        EROFS,
  6472.         ERROR_RENAME_ACROSS_DEVICES,    EXDEV,
  6473.         ERROR_DIRECTORY_NOT_EMPTY,        ENOTEMPTY,
  6474.         ERROR_TOO_MANY_LEVELS,            ENAMETOOLONG,
  6475.         ERROR_DEVICE_NOT_MOUNTED,        ENXIO,
  6476.         ERROR_SEEK_ERROR,                EIO,
  6477.         ERROR_COMMENT_TOO_BIG,            ENAMETOOLONG,
  6478.         ERROR_DISK_FULL,                ENOSPC,
  6479.         ERROR_DELETE_PROTECTED,            EACCES,
  6480.         ERROR_WRITE_PROTECTED,            EACCES,
  6481.         ERROR_READ_PROTECTED,            EACCES,
  6482.         ERROR_NOT_A_DOS_DISK,            EFTYPE,
  6483.         ERROR_NO_DISK,                    EACCES,
  6484.         ERROR_NO_MORE_ENTRIES,            EIO,
  6485.         ERROR_IS_SOFT_LINK,                EFTYPE,
  6486.         ERROR_OBJECT_LINKED,            EIO,
  6487.         ERROR_BAD_HUNK,                    ENOEXEC,
  6488.         ERROR_NOT_IMPLEMENTED,            ENOSYS,
  6489.         ERROR_RECORD_NOT_LOCKED,        EIO,
  6490.         ERROR_LOCK_COLLISION,            EACCES,
  6491.         ERROR_LOCK_TIMEOUT,                EIO,
  6492.         ERROR_UNLOCK_ERROR,                EIO,
  6493.         ERROR_BUFFER_OVERFLOW,            EIO,
  6494.         ERROR_BREAK,                    EINTR,
  6495.         ERROR_NOT_EXECUTABLE,            ENOEXEC
  6496.     };
  6497.  
  6498.     LONG ioErr = IoErr();
  6499.     int i;
  6500.  
  6501.     /* If nothing else matches, we can always
  6502.      * flag it as an I/O error.
  6503.      */
  6504.     errno = EIO;
  6505.  
  6506.     for(i = 0 ; i < NUM_ENTRIES(MapTable) ; i++)
  6507.     {
  6508.         if(MapTable[i].IoErr == ioErr)
  6509.         {
  6510.             errno = MapTable[i].errno;
  6511.             break;
  6512.         }
  6513.     }
  6514. }
  6515.  
  6516. /******************************************************************************/
  6517.  
  6518. off_t
  6519. amiga_lseek(int fd,off_t offset,int mode)
  6520. {
  6521.     struct UFB * ufb;
  6522.     off_t result = ERROR;
  6523.  
  6524.     ENTER();
  6525.     SHOWVALUE(fd);
  6526.     SHOWVALUE(offset);
  6527.     SHOWVALUE(mode);
  6528.  
  6529.     ForbidDOS();
  6530.  
  6531.     /* Make sure that we operate on a file. */
  6532.     ufb = chkufb(fd);
  6533.     if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6534.         result = lseek(fd,offset,mode);
  6535.     else
  6536.         errno = EBADF;
  6537.  
  6538.     PermitDOS();
  6539.  
  6540.     RETURN(result);
  6541.     return(result);
  6542. }
  6543.  
  6544. /******************************************************************************/
  6545.  
  6546. int
  6547. amiga_chroot(char *name)    /* dummy */
  6548. {
  6549.     int result = OK;
  6550.  
  6551.     ENTER();
  6552.  
  6553.     SHOWSTRING(name);
  6554.  
  6555.     RETURN(result);
  6556.     return(result);
  6557. }
  6558.  
  6559. /******************************************************************************/
  6560.  
  6561. STATIC int
  6562. MapFileNameAmigaToUnix(
  6563.     const char *    amiga,
  6564.     char *            unix,
  6565.     int                maxUnixLen)
  6566. {
  6567.     int len,destLen;
  6568.     int result = ERROR;
  6569.  
  6570.     /* This routine makes a Unix file
  6571.      * name generated from an AmigaDOS
  6572.      * file name. This involves a slight
  6573.      * change of syntax...
  6574.      */
  6575.     D(("amiga name |%s|",amiga));
  6576.  
  6577.     len = destLen = strlen(amiga);
  6578.     if(amiga[0] == '/')
  6579.     {
  6580.         destLen = 2 + len;
  6581.     }
  6582.     else
  6583.     {
  6584.         int i;
  6585.  
  6586.         for(i = 0 ; i < len ; i++)
  6587.         {
  6588.             if(amiga[i] == ':')
  6589.             {
  6590.                 if(amiga[i+1] != '\0')
  6591.                     destLen = 1 + len;
  6592.  
  6593.                 break;
  6594.             }
  6595.         }
  6596.     }
  6597.  
  6598.     if(destLen < maxUnixLen)
  6599.     {
  6600.         if(amiga[0] == '/')
  6601.         {
  6602.             /* `/foo\0' -> `../foo\0' */
  6603.             memmove(&unix[2],amiga,len+1);
  6604.             strncpy(unix,"..",2);
  6605.         }
  6606.         else
  6607.         {
  6608.             BOOL done = FALSE;
  6609.             int i;
  6610.  
  6611.             for(i = 0 ; i < len ; i++)
  6612.             {
  6613.                 if(amiga[i] == ':')
  6614.                 {
  6615.                     if(amiga[i+1] == '\0')
  6616.                     {
  6617.                         /* `foo:\0' -> `/foo\0' */
  6618.                         memmove(&unix[1],amiga,i);
  6619.                         unix[0] = '/';
  6620.                         unix[i+1] = '\0';
  6621.                     }
  6622.                     else
  6623.                     {
  6624.                         /* `foo:bar\0' -> `/foo/bar\0' */
  6625.                         memmove(&unix[1],amiga,len+1);
  6626.                         unix[0] = '/';
  6627.                         unix[i+1] = '/';
  6628.                     }
  6629.  
  6630.                     done = TRUE;
  6631.                     break;
  6632.                 }
  6633.             }
  6634.  
  6635.             if(NOT done && unix != amiga)
  6636.                 strcpy(unix,amiga);
  6637.         }
  6638.  
  6639.         D(("unix name |%s|",unix));
  6640.  
  6641.         result = OK;
  6642.     }
  6643.     else
  6644.     {
  6645.         SHOWMSG("unix name is too long to fit");
  6646.  
  6647.         errno = ENAMETOOLONG;
  6648.     }
  6649.  
  6650.     return(result);
  6651. }
  6652.  
  6653. /******************************************************************************/
  6654.  
  6655. STATIC VOID
  6656. FlushSTDOUT(VOID)
  6657. {
  6658.     /* Flush the standard output streams so that
  6659.      * any following output will be printed after
  6660.      * any buffered stdio output.
  6661.      */
  6662.     if(WBenchMsg == NULL)
  6663.     {
  6664.         struct UFB * ufb;
  6665.  
  6666.         /* Don't let anybody stop us. */
  6667.         signal(SIGINT,SIG_IGN);
  6668.         signal(SIGTERM,SIG_IGN);
  6669.  
  6670.         ufb = chkufb(fileno(stdout));
  6671.         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6672.             fflush(stdout);
  6673.  
  6674.         ufb = chkufb(fileno(stderr));
  6675.         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6676.             fflush(stderr);
  6677.     }
  6678. }
  6679.  
  6680. VOID
  6681. _CXOVF(VOID)
  6682. {
  6683.     /* This routine is called when a stack overflow occurs. */
  6684.     FlushSTDOUT();
  6685.     ReportProblem("Stack overflow");
  6686.  
  6687.     exit(RETURN_ERROR);
  6688. }
  6689.  
  6690. VOID __regargs
  6691. _CXBRK(VOID)
  6692. {
  6693.     extern STRPTR _ProgramName;
  6694.  
  6695.     FlushSTDOUT();
  6696.  
  6697.     /* This routine is called when the program is interrupted. */
  6698.     if(DOSBase->lib_Version >= 37)
  6699.     {
  6700.         PrintFault(ERROR_BREAK,_ProgramName);
  6701.     }
  6702.     else
  6703.     {
  6704.         const char *famousLastWords = ": *** Break";
  6705.         BPTR output = Output();
  6706.  
  6707.         Write(output,(APTR)famousLastWords,strlen(famousLastWords));
  6708.         Write(output,_ProgramName,strlen(_ProgramName));
  6709.         Write(output,"\n",1);
  6710.     }
  6711.  
  6712.     exit(RETURN_WARN);
  6713. }
  6714.  
  6715. /******************************************************************************/
  6716.  
  6717. STATIC STRPTR SambaSemaphoreName = "Amiga Samba";
  6718.  
  6719. struct SambaClientNode
  6720. {
  6721.     struct MinNode    scn_MinNode;
  6722.     struct Task *    scn_Task;
  6723.     pid_t            scn_PID;
  6724. };
  6725.  
  6726. struct SambaSemaphore
  6727. {
  6728.     struct SignalSemaphore    ss_Semaphore;
  6729.     struct List                ss_ClientList;
  6730.     pid_t                    ss_PID;
  6731.     struct List                ss_FileLockList;
  6732. };
  6733.  
  6734. STATIC struct SambaSemaphore *    SambaSemaphore;
  6735. STATIC struct SambaClientNode *    ThisClient;
  6736.  
  6737. STATIC VOID
  6738. CleanupSambaSemaphore(VOID)
  6739. {
  6740.     if(ThisClient != NULL)
  6741.     {
  6742.         /* Unregister the program. */
  6743.         ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6744.         Remove((struct Node *)ThisClient);
  6745.         ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6746.  
  6747.         FreeVec(ThisClient);
  6748.         ThisClient = NULL;
  6749.     }
  6750. }
  6751.  
  6752. STATIC BOOL
  6753. SetupSambaSemaphore(VOID)
  6754. {
  6755.     BOOL success = FALSE;
  6756.  
  6757.     /* We have to have the timer open to serialize the process IDs properly. */
  6758.     if(TimerBase != NULL)
  6759.     {
  6760.         Forbid();
  6761.  
  6762.         /* Try to find the global rendezvous semaphore. */
  6763.         SambaSemaphore = (struct SambaSemaphore *)FindSemaphore(SambaSemaphoreName);
  6764.         if(SambaSemaphore == NULL)
  6765.         {
  6766.             /* Couldn't find it. So, we create it... */
  6767.             SambaSemaphore = AllocMem(sizeof(*SambaSemaphore) + strlen(SambaSemaphoreName)+1,MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6768.             if(SambaSemaphore != NULL)
  6769.             {
  6770.                 /* Set up the name. */
  6771.                 SambaSemaphore->ss_Semaphore.ss_Link.ln_Name = (char *)(SambaSemaphore+1);
  6772.                 strcpy(SambaSemaphore->ss_Semaphore.ss_Link.ln_Name,SambaSemaphoreName);
  6773.  
  6774.                 /* Set the base value for all process IDs. */
  6775.                 SambaSemaphore->ss_PID = 936;
  6776.  
  6777.                 /* Clear the client list tasks are going to be registered with. */
  6778.                 NewList(&SambaSemaphore->ss_ClientList);
  6779.  
  6780.                 /* Clear the list we will use for keeping
  6781.                  * track of file segment locks.
  6782.                  */
  6783.                 NewList(&SambaSemaphore->ss_FileLockList);
  6784.  
  6785.                 AddSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6786.             }
  6787.         }
  6788.  
  6789.         Permit();
  6790.     }
  6791.  
  6792.     /* If possible, register this task. */
  6793.     if(SambaSemaphore != NULL)
  6794.     {
  6795.         struct SambaClientNode * scn;
  6796.  
  6797.         scn = AllocVec(sizeof(*scn),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6798.         if(scn != NULL)
  6799.         {
  6800.             LONG max_cli,i;
  6801.  
  6802.             /* That's me. */
  6803.             scn->scn_Task = FindTask(NULL);
  6804.  
  6805.             /* Now for the interesting part: assign a PID to this
  6806.              * process which matches its CLI task number.
  6807.              */
  6808.             Forbid();
  6809.  
  6810.             max_cli = MaxCli();
  6811.             for(i = 1 ; i <= max_cli ; i++)
  6812.             {
  6813.                 if(FindCliProc(i) == (struct Process *)scn->scn_Task)
  6814.                 {
  6815.                     scn->scn_PID = i;
  6816.                     break;
  6817.                 }
  6818.             }
  6819.  
  6820.             Permit();
  6821.  
  6822.             ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6823.             AddTail(&SambaSemaphore->ss_ClientList,(struct Node *)scn);
  6824.             ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6825.  
  6826.             ThisClient = scn;
  6827.  
  6828.             success = TRUE;
  6829.         }
  6830.     }
  6831.  
  6832.     return(success);
  6833. }
  6834.  
  6835. int
  6836. amiga_kill(pid_t pid,int sig)
  6837. {
  6838.     struct SambaClientNode * scn;
  6839.     struct Task * found = NULL;
  6840.     int result = ERROR;
  6841.  
  6842.     chkabort();
  6843.  
  6844.     ENTER();
  6845.  
  6846.     ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6847.  
  6848.     /* Try to find the Samba program that responds
  6849.      * to the given process ID.
  6850.      */
  6851.     for(scn = (struct SambaClientNode *)SambaSemaphore->ss_ClientList.lh_Head ;
  6852.         scn->scn_MinNode.mln_Succ != NULL ;
  6853.         scn = (struct SambaClientNode *)scn->scn_MinNode.mln_Succ)
  6854.     {
  6855.         if(scn->scn_PID == pid)
  6856.         {
  6857.             found = scn->scn_Task;
  6858.             break;
  6859.         }
  6860.     }
  6861.  
  6862.     /* Did we find one? */
  6863.     if(found != NULL)
  6864.     {
  6865.         /* Kill the task or just do nothing? */
  6866.         if(sig == SIGTERM)
  6867.             Signal(found,SIGBREAKF_CTRL_C);
  6868.  
  6869.         result = OK;
  6870.     }
  6871.     else
  6872.     {
  6873.         errno = ESRCH;
  6874.     }
  6875.  
  6876.     ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6877.  
  6878.     RETURN(result);
  6879.     return(result);
  6880. }
  6881.  
  6882. pid_t
  6883. amiga_getpid(VOID)
  6884. {
  6885.     pid_t result;
  6886.  
  6887.     chkabort();
  6888.  
  6889.     ENTER();
  6890.  
  6891.     /* Return this program's process ID. */
  6892.     result = ThisClient->scn_PID;
  6893.  
  6894.     RETURN(result);
  6895.     return(result);
  6896. }
  6897.  
  6898. /******************************************************************************/
  6899.  
  6900. struct LockedRegionNode
  6901. {
  6902.     struct MinNode    lrn_MinNode;
  6903.     LONG            lrn_Start;
  6904.     LONG            lrn_Stop;
  6905.     pid_t            lrn_Owner;
  6906.     BOOL            lrn_Shared;
  6907. };
  6908.  
  6909. struct FileLockNode
  6910. {
  6911.     struct MinNode    fln_MinNode;
  6912.     struct List        fln_LockedRegionList;
  6913.     BPTR            fln_FileParentDir;
  6914.     UBYTE            fln_FileName[1];
  6915. };
  6916.  
  6917. STATIC VOID
  6918. RemoveLockedRegionNode(struct UFB * ufb,LONG start,LONG stop)
  6919. {
  6920.     if(FLAG_IS_SET(ufb->ufbflg,UFB_LOCKED))
  6921.     {
  6922.         BPTR fileHandle = (BPTR)ufb->ufbfh;
  6923.         struct FileLockNode * whichLock;
  6924.  
  6925.         /* Find the locked file this descriptor
  6926.          * buffer belongs to.
  6927.          */
  6928.         if(FindFileLockNodeByFileHandle(fileHandle,&whichLock) == OK && whichLock != NULL)
  6929.         {
  6930.             struct LockedRegionNode * lrn;
  6931.  
  6932.             /* Find the region to unlock and remove it. */
  6933.             for(lrn = (struct LockedRegionNode *)whichLock->fln_LockedRegionList.lh_Head ;
  6934.                 lrn->lrn_MinNode.mln_Succ != NULL ;
  6935.                 lrn = (struct LockedRegionNode *)lrn->lrn_MinNode.mln_Succ)
  6936.             {
  6937.                 if(lrn->lrn_Owner == ThisClient->scn_PID &&
  6938.                    lrn->lrn_Start == start &&
  6939.                    lrn->lrn_Stop  == stop)
  6940.                 {
  6941.                     SHOWMSG("unlocking all regions on this file");
  6942.  
  6943.                     Remove((struct Node *)lrn);
  6944.                     DeleteLockedRegionNode(lrn);
  6945.                     break;
  6946.                 }
  6947.             }
  6948.  
  6949.             /* Check if there are any locked regions left.
  6950.              * If not, mark the entire file as unlocked.
  6951.              */
  6952.             if(IsListEmpty(&whichLock->fln_LockedRegionList))
  6953.             {
  6954.                 SHOWMSG("no more regions are locked; removing the file lock node");
  6955.  
  6956.                 Remove((struct Node *)whichLock);
  6957.  
  6958.                 DeleteFileLockNode(whichLock);
  6959.  
  6960.                 CLEAR_FLAG(ufb->ufbflg,UFB_LOCKED);
  6961.             }
  6962.         }
  6963.     }
  6964. }
  6965.  
  6966. STATIC VOID
  6967. DeleteLockedRegionNode(struct LockedRegionNode * lrn)
  6968. {
  6969.     if(lrn != NULL)
  6970.         FreeMem(lrn,sizeof(*lrn));
  6971. }
  6972.  
  6973. STATIC LONG
  6974. CreateLockedRegionNode(struct LockedRegionNode ** resultPtr)
  6975. {
  6976.     struct LockedRegionNode * lrn;
  6977.     LONG error;
  6978.  
  6979.     lrn = AllocMem(sizeof(*lrn),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6980.     if(lrn != NULL)
  6981.     {
  6982.         lrn->lrn_Owner = ThisClient->scn_PID;
  6983.  
  6984.         error = OK;
  6985.     }
  6986.     else
  6987.     {
  6988.         error = ERROR_NO_FREE_STORE;
  6989.     }
  6990.  
  6991.     (*resultPtr) = lrn;
  6992.  
  6993.     return(error);
  6994. }
  6995.  
  6996. STATIC VOID
  6997. DeleteFileLockNode(struct FileLockNode * fln)
  6998. {
  6999.     if(fln != NULL)
  7000.     {
  7001.         UnLock(fln->fln_FileParentDir);
  7002.         FreeVec(fln);
  7003.     }
  7004. }
  7005.  
  7006. STATIC LONG
  7007. CreateFileLockNode(struct UFB * ufb,struct FileLockNode ** resultPtr)
  7008. {
  7009.     struct FileLockNode * result = NULL;
  7010.     BPTR fileHandle = (BPTR)ufb->ufbfh;
  7011.     D_S(struct FileInfoBlock,fib);
  7012.     LONG error = OK;
  7013.  
  7014.     /* We store a lock on the file's parent directory
  7015.      * and the name of the file for later use in
  7016.      * comparisons.
  7017.      */
  7018.     if(ExamineFH(fileHandle,fib))
  7019.     {
  7020.         struct FileLockNode * fln;
  7021.  
  7022.         fln = AllocVec(sizeof(*fln) + strlen(fib->fib_FileName),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  7023.         if(fln != NULL)
  7024.         {
  7025.             fln->fln_FileParentDir = ParentOfFH(fileHandle);
  7026.             if(fln->fln_FileParentDir != ZERO)
  7027.             {
  7028.                 strcpy(fln->fln_FileName,fib->fib_FileName);
  7029.  
  7030.                 NewList(&fln->fln_LockedRegionList);
  7031.  
  7032.                 result = fln;
  7033.                 fln = NULL;
  7034.             }
  7035.             else
  7036.             {
  7037.                 error = IoErr();
  7038.             }
  7039.  
  7040.             DeleteFileLockNode(fln);
  7041.         }
  7042.         else
  7043.         {
  7044.             error = ERROR_NO_FREE_STORE;
  7045.         }
  7046.     }
  7047.     else
  7048.     {
  7049.         error = IoErr();
  7050.     }
  7051.  
  7052.     (*resultPtr) = result;
  7053.  
  7054.     return(error);
  7055. }
  7056.  
  7057. STATIC LONG
  7058. FindFileLockNodeByFileHandle(BPTR fileHandle,struct FileLockNode ** resultPtr)
  7059. {
  7060.     struct FileLockNode * result = NULL;
  7061.     BPTR parentDir;
  7062.     LONG error;
  7063.  
  7064.     /* Determine the file's parent directory and
  7065.      * name. These will be compared against the
  7066.      * global file lock data.
  7067.      */
  7068.     parentDir = ParentOfFH(fileHandle);
  7069.     if(parentDir != ZERO)
  7070.     {
  7071.         D_S(struct FileInfoBlock,this_fib);
  7072.  
  7073.         if(ExamineFH(fileHandle,this_fib))
  7074.         {
  7075.             struct FileLockNode * fln;
  7076.  
  7077.             #if DEBUG
  7078.             {
  7079.                 char name[MAX_FILENAME_LEN];
  7080.  
  7081.                 if(NameFromFH(fileHandle,name,sizeof(name)))
  7082.                     D(("Looking for a lock on file |%s|",name));
  7083.             }
  7084.             #endif /* DEBUG */
  7085.  
  7086.             error = OK;
  7087.  
  7088.             for(fln = (struct FileLockNode *)SambaSemaphore->ss_FileLockList.lh_Head ;
  7089.                 fln->fln_MinNode.mln_Succ != NULL ;
  7090.                 fln = (struct FileLockNode *)fln->fln_MinNode.mln_Succ)
  7091.             {
  7092.                 /* To be identical, the files must reside in the
  7093.                  * same directories and bear the same names.
  7094.                  */
  7095.                 if(SameLock(fln->fln_FileParentDir,parentDir) == LOCK_SAME)
  7096.                 {
  7097.                     if(Stricmp(fln->fln_FileName,this_fib->fib_FileName) == SAME)
  7098.                     {
  7099.                         result = fln;
  7100.                         error = OK;
  7101.  
  7102.                         break;
  7103.                     }
  7104.                 }
  7105.             }
  7106.         }
  7107.         else
  7108.         {
  7109.             error = IoErr();
  7110.         }
  7111.  
  7112.         if(result != NULL)
  7113.             SHOWMSG("found one");
  7114.         else
  7115.             SHOWMSG("didn't find one");
  7116.  
  7117.         UnLock(parentDir);
  7118.     }
  7119.     else
  7120.     {
  7121.         error = IoErr();
  7122.     }
  7123.  
  7124.     (*resultPtr) = result;
  7125.  
  7126.     return(error);
  7127. }
  7128.  
  7129. STATIC VOID
  7130. FindFileLockNodeByDrawerAndName(BPTR dirLock,STRPTR fileName,struct FileLockNode ** resultPtr)
  7131. {
  7132.     struct FileLockNode * result = NULL;
  7133.     struct FileLockNode * fln;
  7134.  
  7135.     /* This is a somewhat simplied version of FindFileLockNodeByFileHandle()
  7136.      * which works with preset drawer and name data.
  7137.      */
  7138.  
  7139.     #if DEBUG
  7140.     {
  7141.         char name[MAX_FILENAME_LEN];
  7142.  
  7143.         if(NameFromLock(dirLock,name,sizeof(name)))
  7144.         {
  7145.             if(AddPart(name,fileName,sizeof(name)))
  7146.                 D(("Looking for a lock on file |%s|",name));
  7147.         }
  7148.     }
  7149.     #endif /* DEBUG */
  7150.  
  7151.     for(fln = (struct FileLockNode *)SambaSemaphore->ss_FileLockList.lh_Head ;
  7152.         fln->fln_MinNode.mln_Succ != NULL ;
  7153.         fln = (struct FileLockNode *)fln->fln_MinNode.mln_Succ)
  7154.     {
  7155.         if(SameLock(fln->fln_FileParentDir,dirLock) == LOCK_SAME)
  7156.         {
  7157.             if(Stricmp(fln->fln_FileName,fileName) == SAME)
  7158.             {
  7159.                 result = fln;
  7160.  
  7161.                 break;
  7162.             }
  7163.         }
  7164.     }
  7165.  
  7166.     if(result != NULL)
  7167.         SHOWMSG("found one");
  7168.     else
  7169.         SHOWMSG("didn't find one");
  7170.  
  7171.     (*resultPtr) = result;
  7172. }
  7173.  
  7174. STATIC struct LockedRegionNode *
  7175. FindCollidingRegion(struct FileLockNode * fln,LONG start,LONG stop,BOOL shared)
  7176. {
  7177.     struct LockedRegionNode * result = NULL;
  7178.     struct LockedRegionNode * lrn;
  7179.  
  7180.     /* This routine looks for a locked region that overlaps
  7181.      * with the specified region. It returns a pointer to the
  7182.      * region that would collide with the specified region if
  7183.      * a new lock were to be added.
  7184.      */
  7185.     for(lrn = (struct LockedRegionNode *)fln->fln_LockedRegionList.lh_Head ;
  7186.         lrn->lrn_MinNode.mln_Succ != NULL ;
  7187.         lrn = (struct LockedRegionNode *)lrn->lrn_MinNode.mln_Succ)
  7188.     {
  7189.         /* Do the regions overlap? */
  7190.         if(lrn->lrn_Start <= stop && start <= lrn->lrn_Stop)
  7191.         {
  7192.             /* Two shared regions may always overlap.
  7193.              * How about the rest?
  7194.              */
  7195.             if(NOT shared || NOT lrn->lrn_Shared)
  7196.             {
  7197.                 /* The lock owner may add as many exclusive
  7198.                  * or shared locks to the same region as
  7199.                  * necessary.
  7200.                  */
  7201.                 if(lrn->lrn_Owner == ThisClient->scn_PID)
  7202.                     continue;
  7203.  
  7204.                 /* So we found a region that would
  7205.                  * cause a collision.
  7206.                  */
  7207.                 result = lrn;
  7208.                 break;
  7209.             }
  7210.         }
  7211.     }
  7212.  
  7213.     return(result);
  7214. }
  7215.  
  7216. STATIC VOID
  7217. CleanupFileLocks(int fd)
  7218. {
  7219.     struct UFB * ufb;
  7220.  
  7221.     /* This routine removes all locked regions from a file
  7222.      * before it is eventually closed.
  7223.      */
  7224.  
  7225.     ufb = chkufb(fd);
  7226.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_LOCKED))
  7227.     {
  7228.         BPTR fileHandle = (BPTR)ufb->ufbfh;
  7229.         struct FileLockNode * whichLock;
  7230.  
  7231.         ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7232.  
  7233.         if(FindFileLockNodeByFileHandle(fileHandle,&whichLock) == OK && whichLock != NULL)
  7234.         {
  7235.             struct LockedRegionNode * lrn_this;
  7236.             struct LockedRegionNode * lrn_next;
  7237.  
  7238.             SHOWMSG("unlocking all regions on this file");
  7239.  
  7240.             for(lrn_this = (struct LockedRegionNode *)whichLock->fln_LockedRegionList.lh_Head ;
  7241.                (lrn_next = (struct LockedRegionNode *)lrn_this->lrn_MinNode.mln_Succ) != NULL ;
  7242.                 lrn_this = lrn_next)
  7243.             {
  7244.                 if(lrn_this->lrn_Owner == ThisClient->scn_PID)
  7245.                 {
  7246.                     Remove((struct Node *)lrn_this);
  7247.                     DeleteLockedRegionNode(lrn_this);
  7248.                 }
  7249.             }
  7250.  
  7251.             if(IsListEmpty(&whichLock->fln_LockedRegionList))
  7252.             {
  7253.                 SHOWMSG("no more regions are locked; removing the file lock node");
  7254.  
  7255.                 Remove((struct Node *)whichLock);
  7256.  
  7257.                 DeleteFileLockNode(whichLock);
  7258.             }
  7259.         }
  7260.  
  7261.         CLEAR_FLAG(ufb->ufbflg,UFB_LOCKED);
  7262.  
  7263.         ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7264.     }
  7265. }
  7266.  
  7267. #define SEEK_ERROR (-1)
  7268.  
  7269. STATIC int
  7270. HandleFileLocking(int cmd,struct flock * l,struct UFB * ufb)
  7271. {
  7272.     int result = ERROR;
  7273.  
  7274.     /* This routine implements advisory file segment locking
  7275.      * similar to 4.4BSD, but not quite the same. The functionality
  7276.      * is a subset, somewhat similar to the functionality offered
  7277.      * by the AmigaDOS LockRecord() and UnlockRecord() functions.
  7278.      * This means for example that every unlock request must
  7279.      * match the size and position of the corresponding locking
  7280.      * request.
  7281.      *
  7282.      * This implementation was chosen because not every Amiga
  7283.      * filing system implements record locking and Samba
  7284.      * absolutely requires this functionality to work.
  7285.      */
  7286.     if(l != NULL && ufb != NULL)
  7287.     {
  7288.         /* Can we make sense of the input parameters? */
  7289.         if(F_RDLCK <= l->l_type && l->l_type <= F_WRLCK &&
  7290.           (l->l_whence == SEEK_SET || l->l_whence == SEEK_CUR || l->l_whence == SEEK_END))
  7291.         {
  7292.             struct LockedRegionNode * lrn = NULL;
  7293.             struct FileLockNode * fln = NULL;
  7294.             LONG error;
  7295.  
  7296.             if((cmd == F_SETLK || cmd == F_SETLKW) && (l->l_type != F_UNLCK))
  7297.             {
  7298.                 SHOWMSG("this is a lock request");
  7299.                 error = CreateFileLockNode(ufb,&fln);
  7300.                 if(error == OK)
  7301.                     error = CreateLockedRegionNode(&lrn);
  7302.             }
  7303.             else
  7304.             {
  7305.                 SHOWMSG("this is not a lock request");
  7306.                 error = OK;
  7307.             }
  7308.  
  7309.             if(error == OK)
  7310.             {
  7311.                 D_S(struct FileInfoBlock,fib);
  7312.                 BPTR fileHandle = (BPTR)ufb->ufbfh;
  7313.                 BOOL dataIsValid = TRUE;
  7314.                 LONG currentPosition;
  7315.                 LONG start = 0;
  7316.                 LONG len = 0;
  7317.  
  7318.                 /* Now calculate the position of the
  7319.                  * first byte to lock and the number
  7320.                  * of bytes to lock.
  7321.                  */
  7322.                 switch(l->l_whence)
  7323.                 {
  7324.                     case SEEK_SET:
  7325.  
  7326.                         start = l->l_start;
  7327.  
  7328.                         if(l->l_len == 0)
  7329.                         {
  7330.                             if(ExamineFH(fileHandle,fib))
  7331.                                 len = fib->fib_Size - start;
  7332.                             else
  7333.                                 dataIsValid = FALSE;
  7334.                         }
  7335.                         else
  7336.                         {
  7337.                             len = l->l_len;
  7338.                         }
  7339.  
  7340.                         break;
  7341.  
  7342.                     case SEEK_CUR:
  7343.  
  7344.                         currentPosition = Seek(fileHandle,0,OFFSET_CURRENT);
  7345.                         if(currentPosition != SEEK_ERROR)
  7346.                         {
  7347.                             start = currentPosition + l->l_start;
  7348.  
  7349.                             if(l->l_len == 0)
  7350.                             {
  7351.                                 if(ExamineFH(fileHandle,fib))
  7352.                                     len = fib->fib_Size - start;
  7353.                                 else
  7354.                                     dataIsValid = FALSE;
  7355.                             }
  7356.                             else
  7357.                             {
  7358.                                 len = l->l_len;
  7359.                             }
  7360.                         }
  7361.                         else
  7362.                         {
  7363.                             dataIsValid = FALSE;
  7364.                         }
  7365.  
  7366.                         break;
  7367.  
  7368.                     case SEEK_END:
  7369.                     default:
  7370.  
  7371.                         if(ExamineFH(fileHandle,fib))
  7372.                         {
  7373.                             start = fib->fib_Size + l->l_start;
  7374.  
  7375.                             if(l->l_len == 0)
  7376.                                 len = fib->fib_Size - start;
  7377.                             else
  7378.                                 len = l->l_len;
  7379.                         }
  7380.                         else
  7381.                         {
  7382.                             dataIsValid = FALSE;
  7383.                         }
  7384.  
  7385.                         break;
  7386.                 }
  7387.  
  7388.                 SHOWVALUE(start);
  7389.                 SHOWVALUE(len);
  7390.  
  7391.                 /* Did we get everything we needed? */
  7392.                 if(dataIsValid)
  7393.                 {
  7394.                     if(start >= 0 && len >= 0)
  7395.                     {
  7396.                         if(len > 0)
  7397.                         {
  7398.                             if(l->l_type == F_UNLCK)
  7399.                             {
  7400.                                 D(("unlocking %ld..%ld",start,start+len-1));
  7401.  
  7402.                                 ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7403.  
  7404.                                 RemoveLockedRegionNode(ufb,start,start+len-1);
  7405.  
  7406.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7407.  
  7408.                                 result = OK;
  7409.                             }
  7410.                             else if(cmd == F_SETLKW)
  7411.                             {
  7412.                                 BPTR parentDir;
  7413.  
  7414.                                 D(("  locking %ld..%ld",start,start+len-1));
  7415.  
  7416.                                 parentDir = ParentOfFH(fileHandle);
  7417.                                 if(parentDir != ZERO)
  7418.                                 {
  7419.                                     D_S(struct FileInfoBlock,fib);
  7420.  
  7421.                                     if(ExamineFH(fileHandle,fib))
  7422.                                     {
  7423.                                         BOOL shared = (BOOL)(l->l_type == F_RDLCK);
  7424.                                         struct FileLockNode * existing_fln;
  7425.                                         BOOL stopped = FALSE;
  7426.                                         BOOL locked;
  7427.  
  7428.                                         if(shared)
  7429.                                             D(("this is a shared lock; waiting for completion"));
  7430.                                         else
  7431.                                             D(("this is an exclusive lock; waiting for completion"));
  7432.  
  7433.                                         lrn->lrn_Start    = start;
  7434.                                         lrn->lrn_Stop    = start+len-1;
  7435.                                         lrn->lrn_Shared    = shared;
  7436.  
  7437.                                         /* Retry until we manage to lock the record. */
  7438.                                         locked = FALSE;
  7439.                                         do
  7440.                                         {
  7441.                                             ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7442.  
  7443.                                             FindFileLockNodeByDrawerAndName(parentDir,fib->fib_FileName,&existing_fln);
  7444.                                             if(existing_fln != NULL)
  7445.                                             {
  7446.                                                 SHOWMSG("that file is already locked by someone");
  7447.  
  7448.                                                 if(FindCollidingRegion(existing_fln,start,start+len-1,shared) == NULL)
  7449.                                                 {
  7450.                                                     SHOWMSG("but the locks don't collide");
  7451.  
  7452.                                                     AddTail(&existing_fln->fln_LockedRegionList,(struct Node *)lrn);
  7453.                                                     lrn = NULL;
  7454.  
  7455.                                                     locked = TRUE;
  7456.                                                 }
  7457.                                                 else
  7458.                                                 {
  7459.                                                     SHOWMSG("and the locks collide");
  7460.                                                 }
  7461.                                             }
  7462.                                             else
  7463.                                             {
  7464.                                                 SHOWMSG("nobody has any locks on this file");
  7465.  
  7466.                                                 AddTail(&SambaSemaphore->ss_FileLockList,(struct Node *)fln);
  7467.                                                 AddTail(&fln->fln_LockedRegionList,(struct Node *)lrn);
  7468.  
  7469.                                                 fln = NULL;
  7470.                                                 lrn = NULL;
  7471.  
  7472.                                                 locked = TRUE;
  7473.                                             }
  7474.  
  7475.                                             ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7476.  
  7477.                                             if(NOT locked)
  7478.                                             {
  7479.                                                 const int randMax = RAND_MAX / 65536;
  7480.                                                 LONG numRandomTicks;
  7481.  
  7482.                                                 if(CheckAbort())
  7483.                                                 {
  7484.                                                     stopped = TRUE;
  7485.                                                     break;
  7486.                                                 }
  7487.  
  7488.                                                 /* Wait a little before retrying
  7489.                                                  * the locking operation. We add
  7490.                                                  * a little randomness here to
  7491.                                                  * reduce the likelihood of two
  7492.                                                  * competing processes trying to
  7493.                                                  * lock the same file at the
  7494.                                                  * same time.
  7495.                                                  */
  7496.  
  7497.                                                 numRandomTicks = ((TICKS_PER_SECOND / 2) * (rand() / 65536)) / randMax;
  7498.  
  7499.                                                 if(numRandomTicks > 0)
  7500.                                                     Delay(numRandomTicks);
  7501.                                             }
  7502.                                         }
  7503.                                         while(NOT locked);
  7504.  
  7505.                                         if(stopped)
  7506.                                         {
  7507.                                             SHOWMSG("lock polling loop stopped");
  7508.  
  7509.                                             DeleteFileLockNode(fln);
  7510.                                             fln = NULL;
  7511.  
  7512.                                             DeleteLockedRegionNode(lrn);
  7513.                                             lrn = NULL;
  7514.  
  7515.                                             UnLock(parentDir);
  7516.                                             parentDir = ZERO;
  7517.  
  7518.                                             errno = EINTR;
  7519.  
  7520.                                             raise(SIGINT);
  7521.                                         }
  7522.  
  7523.                                         if(locked)
  7524.                                         {
  7525.                                             SHOWMSG("the file now has a lock set");
  7526.                                             SET_FLAG(ufb->ufbflg,UFB_LOCKED);
  7527.                                             result = OK;
  7528.                                         }
  7529.                                     }
  7530.                                     else
  7531.                                     {
  7532.                                         SHOWMSG("couldn't read this file's name");
  7533.                                         MapIoErrToErrno();
  7534.                                     }
  7535.  
  7536.                                     UnLock(parentDir);
  7537.                                 }
  7538.                                 else
  7539.                                 {
  7540.                                     SHOWMSG("couldn't get a lock on the file's parent directory");
  7541.                                     MapIoErrToErrno();
  7542.                                 }
  7543.                             }
  7544.                             else if(cmd == F_SETLK)
  7545.                             {
  7546.                                 BOOL shared = (BOOL)(l->l_type == F_RDLCK);
  7547.                                 struct FileLockNode * existing_fln;
  7548.                                 BOOL locked = FALSE;
  7549.  
  7550.                                 if(shared)
  7551.                                     D(("this is a shared lock"));
  7552.                                 else
  7553.                                     D(("this is an exclusive lock"));
  7554.  
  7555.                                 lrn->lrn_Start    = start;
  7556.                                 lrn->lrn_Stop    = start+len-1;
  7557.                                 lrn->lrn_Shared    = shared;
  7558.  
  7559.                                 ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7560.  
  7561.                                 if(FindFileLockNodeByFileHandle(fileHandle,&existing_fln) == OK)
  7562.                                 {
  7563.                                     if(existing_fln != NULL)
  7564.                                     {
  7565.                                         SHOWMSG("that file is already locked by someone else");
  7566.  
  7567.                                         if(FindCollidingRegion(existing_fln,start,start+len-1,shared) == NULL)
  7568.                                         {
  7569.                                             SHOWMSG("but the locks don't collide");
  7570.  
  7571.                                             AddTail(&existing_fln->fln_LockedRegionList,(struct Node *)lrn);
  7572.                                             lrn = NULL;
  7573.  
  7574.                                             locked = TRUE;
  7575.                                         }
  7576.                                         else
  7577.                                         {
  7578.                                             SHOWMSG("and the locks collide");
  7579.                                         }
  7580.                                     }
  7581.                                     else
  7582.                                     {
  7583.                                         SHOWMSG("nobody has any locks on this file");
  7584.  
  7585.                                         AddTail(&SambaSemaphore->ss_FileLockList,(struct Node *)fln);
  7586.                                         AddTail(&fln->fln_LockedRegionList,(struct Node *)lrn);
  7587.  
  7588.                                         fln = NULL;
  7589.                                         lrn = NULL;
  7590.  
  7591.                                         locked = TRUE;
  7592.                                     }
  7593.                                 }
  7594.  
  7595.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7596.  
  7597.                                 if(locked)
  7598.                                 {
  7599.                                     SHOWMSG("the file now has a lock set");
  7600.  
  7601.                                     SET_FLAG(ufb->ufbflg,UFB_LOCKED);
  7602.  
  7603.                                     result = OK;
  7604.                                 }
  7605.                                 else
  7606.                                 {
  7607.                                     errno = EACCES;
  7608.                                 }
  7609.                             }
  7610.                             else if (cmd == F_GETLK)
  7611.                             {
  7612.                                 struct FileLockNode * fln;
  7613.                                 LONG error;
  7614.  
  7615.                                 SafeObtainSemaphoreShared((struct SignalSemaphore *)SambaSemaphore);
  7616.  
  7617.                                 SHOWMSG("checking for possible lock collision");
  7618.  
  7619.                                 error = FindFileLockNodeByFileHandle(fileHandle,&fln);
  7620.                                 if(error == OK)
  7621.                                 {
  7622.                                     if(fln != NULL)
  7623.                                     {
  7624.                                         struct LockedRegionNode * lrn;
  7625.                                         BOOL shared;
  7626.  
  7627.                                         SHOWMSG("somebody has locked this file");
  7628.  
  7629.                                         shared = (BOOL)(l->l_type == F_RDLCK);
  7630.  
  7631.                                         lrn = FindCollidingRegion(fln,start,start+len-1,shared);
  7632.                                         if(lrn != NULL)
  7633.                                         {
  7634.                                             SHOWMSG("there is a possible lock collision");
  7635.  
  7636.                                             l->l_type    = (lrn->lrn_Shared ? F_RDLCK : F_WRLCK);
  7637.                                             l->l_whence    = SEEK_SET;
  7638.                                             l->l_start    = lrn->lrn_Start;
  7639.                                             l->l_len    = lrn->lrn_Stop - lrn->lrn_Start + 1;
  7640.                                             l->l_pid    = lrn->lrn_Owner;
  7641.                                         }
  7642.                                         else
  7643.                                         {
  7644.                                             SHOWMSG("there is no lock collision");
  7645.  
  7646.                                             l->l_type = F_UNLCK;
  7647.                                         }
  7648.                                     }
  7649.                                     else
  7650.                                     {
  7651.                                         SHOWMSG("nobody has locked this file");
  7652.  
  7653.                                         l->l_type = F_UNLCK;
  7654.                                     }
  7655.  
  7656.                                     result = OK;
  7657.                                 }
  7658.                                 else
  7659.                                 {
  7660.                                     SetIoErr(error);
  7661.  
  7662.                                     MapIoErrToErrno();
  7663.                                 }
  7664.  
  7665.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7666.                             }
  7667.                         }
  7668.                         else
  7669.                         {
  7670.                             SHOWMSG("zero length lock/unlock");
  7671.                             result = OK;
  7672.                         }
  7673.                     }
  7674.                     else
  7675.                     {
  7676.                         SHOWMSG("invalid start/len");
  7677.                         SHOWVALUE(start);
  7678.                         SHOWVALUE(len);
  7679.                         errno = EINVAL;
  7680.                     }
  7681.                 }
  7682.                 else
  7683.                 {
  7684.                     SHOWMSG("couldn't determine start/len");
  7685.                     MapIoErrToErrno();
  7686.                 }
  7687.             }
  7688.             else
  7689.             {
  7690.                 SHOWMSG("couldn't get the bookkeeping memory needed");
  7691.                 MapIoErrToErrno();
  7692.             }
  7693.  
  7694.             DeleteFileLockNode(fln);
  7695.             DeleteLockedRegionNode(lrn);
  7696.         }
  7697.         else
  7698.         {
  7699.             SHOWMSG("invalid lock type or seek offset");
  7700.             SHOWVALUE(l->l_type);
  7701.             SHOWVALUE(l->l_whence);
  7702.             errno = EINVAL;
  7703.         }
  7704.     }
  7705.     else
  7706.     {
  7707.         SHOWMSG("no flock or no ufb");
  7708.         SHOWVALUE(l);
  7709.         SHOWVALUE(ufb);
  7710.  
  7711.         errno = EINVAL;
  7712.     }
  7713.  
  7714.     RETURN(result);
  7715.     return(result);
  7716. }
  7717.  
  7718. int
  7719. amiga_fcntl(int fd,int cmd,unsigned long arg)
  7720. {
  7721.     struct UFB * ufb;
  7722.     struct flock * l;
  7723.     int result = ERROR;
  7724.  
  7725.     chkabort();
  7726.  
  7727.     ENTER();
  7728.  
  7729.     /* Don't try to lock data in a socket... */
  7730.     ufb = chkufb(fd);
  7731.     if(ufb == NULL || FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7732.         ufb = NULL;
  7733.  
  7734.     l = (struct flock *)arg;
  7735.  
  7736.     switch(cmd)
  7737.     {
  7738.         /* Get the first lock that blocks the lock description pointed to
  7739.          * by the third argument, arg, taken as a pointer to a struct
  7740.          * flock (see above).  The information retrieved overwrites the
  7741.          * information passed to fcntl in the flock structure.  If no
  7742.          * lock is found that would prevent this lock from being created,
  7743.          * the structure is left unchanged by this function call except
  7744.          * for the lock type which is set to F_UNLCK.
  7745.          */
  7746.         case F_GETLK:
  7747.  
  7748.             SHOWMSG("F_GETLK");
  7749.             result = HandleFileLocking(cmd,l,ufb);
  7750.             break;
  7751.  
  7752.         /* Set or clear a file segment lock according to the lock de-
  7753.          * scription pointed to by the third argument, arg, taken as a
  7754.          * pointer to a struct flock (see above).    F_SETLK is used to es-
  7755.          * tablish shared (or read) locks (F_RDLCK) or exclusive (or
  7756.          * write) locks, (F_WRLCK), as well as remove either type of lock
  7757.          * (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl
  7758.          * returns immediately with EACCES.
  7759.          */
  7760.         case F_SETLK:
  7761.  
  7762.             SHOWMSG("F_SETLK");
  7763.             result = HandleFileLocking(cmd,l,ufb);
  7764.             break;
  7765.  
  7766.         /* This command is the same as F_SETLK except that if a shared or
  7767.          * exclusive lock is blocked by other locks, the process waits
  7768.          * until the request can be satisfied.  If a signal that is to be
  7769.          * caught is received while fcntl is waiting for a region, the
  7770.          * fcntl will be interrupted if the signal handler has not speci-
  7771.          * fied the SA_RESTART (see sigaction(2)).
  7772.          */
  7773.         case F_SETLKW:
  7774.  
  7775.             SHOWMSG("F_SETLKW");
  7776.             result = HandleFileLocking(cmd,l,ufb);
  7777.             break;
  7778.  
  7779.         /* Get descriptor status flags, as described below (arg is ig-
  7780.          * noted).
  7781.          */
  7782.         case F_GETFL:
  7783.  
  7784.             SHOWMSG("F_GETFL");
  7785.             result = IsDescriptorNonblocking(fd) ? O_NONBLOCK : 0;
  7786.             break;
  7787.  
  7788.         /* Set descriptor status flags to arg. */
  7789.         case F_SETFL:
  7790.  
  7791.             SHOWMSG("F_SETFL");
  7792.             if(FLAG_IS_SET(arg,O_NONBLOCK))
  7793.                 BlockDescriptor(fd);
  7794.             else
  7795.                 UnblockDescriptor(fd);
  7796.  
  7797.             result = OK;
  7798.             break;
  7799.  
  7800.         default:
  7801.  
  7802.             D(("Unknown command %ld",cmd));
  7803.             errno = ENOSYS;
  7804.             break;
  7805.     }
  7806.  
  7807.     RETURN(result);
  7808.     return(result);
  7809. }
  7810.  
  7811. /******************************************************************************/
  7812.  
  7813. int
  7814. amiga_fgetc(FILE *in)
  7815. {
  7816.     struct UFB * ufb;
  7817.     int result = ERROR;
  7818.  
  7819.     PUSH_ASSERTS();
  7820.  
  7821.     chkabort();
  7822.  
  7823.     ufb = chkufb(fileno(in));
  7824.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7825.     {
  7826.         UBYTE c;
  7827.  
  7828.         ENTER();
  7829.         SHOWMSG("input from socket");
  7830.  
  7831.         if(recv(ufb->ufbfh,&c,1,0) == 1)
  7832.             result = c;
  7833.     }
  7834.     else
  7835.     {
  7836.         result = fgetc(in);
  7837.     }
  7838.  
  7839.     RETURN(result);
  7840.     POP();
  7841.     return(result);
  7842. }
  7843.  
  7844. char *
  7845. amiga_fgets(char *str,int n,FILE * in)
  7846. {
  7847.     struct UFB * ufb;
  7848.     char *result;
  7849.  
  7850.     ENTER();
  7851.  
  7852.     ufb = chkufb(fileno(in));
  7853.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7854.     {
  7855.         char *s = str;
  7856.         LONG rc;
  7857.         UBYTE c;
  7858.  
  7859.         SHOWMSG("input from socket");
  7860.         result = str;
  7861.  
  7862.         while(--n > 0)
  7863.         {
  7864.             chkabort();
  7865.  
  7866.             rc = recv(ufb->ufbfh,&c,1,0);
  7867.             if(rc == 1)
  7868.             {
  7869.                 (*str++) = c;
  7870.  
  7871.                 if(c == '\n')
  7872.                     break;
  7873.             }
  7874.             else
  7875.             {
  7876.                 /* End of stream or nothing read? */
  7877.                 if(rc < 0 || str == s)
  7878.                     result = NULL;
  7879.  
  7880.                 break;
  7881.             }
  7882.         }
  7883.  
  7884.         if(result != NULL)
  7885.             (*str) = '\0';
  7886.     }
  7887.     else
  7888.     {
  7889.         result = fgets(str,n,in);
  7890.     }
  7891.  
  7892.     RETURN(result);
  7893.     return(result);
  7894. }
  7895.  
  7896. int
  7897. amiga_fputs(const char *str,FILE *out)
  7898. {
  7899.     struct UFB * ufb;
  7900.     int result;
  7901.  
  7902.     chkabort();
  7903.  
  7904.     ENTER();
  7905.  
  7906.     ufb = chkufb(fileno(out));
  7907.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7908.     {
  7909.         SHOWMSG("output to socket");
  7910.  
  7911.         if(NOT STRING_IS_EMPTY(str))
  7912.             result = send(ufb->ufbfh,str,strlen(str),0);
  7913.         else
  7914.             result = OK;
  7915.  
  7916.         if(result == OK)
  7917.             result = send(ufb->ufbfh,"\n",1,0);
  7918.     }
  7919.     else
  7920.     {
  7921.         result = fputs(str,out);
  7922.     }
  7923.  
  7924.     RETURN(result);
  7925.     return(result);
  7926. }
  7927.  
  7928. int
  7929. amiga_puts(const char *str)
  7930. {
  7931.     int result;
  7932.  
  7933.     result = amiga_fputs(str,stdout);
  7934.  
  7935.     return(result);
  7936. }
  7937.  
  7938. int
  7939. amiga_vfprintf(FILE *out,const char *fmt,va_list args)
  7940. {
  7941.     struct UFB * ufb;
  7942.     int result;
  7943.  
  7944.     chkabort();
  7945.  
  7946.     ENTER();
  7947.  
  7948.     ufb = chkufb(fileno(out));
  7949.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7950.     {
  7951.         char buffer[1024];
  7952.  
  7953.         SHOWMSG("output to socket");
  7954.  
  7955.         vsnprintf(buffer,sizeof(buffer)-1,fmt,args);
  7956.         buffer[sizeof(buffer)-1] = '\0';
  7957.  
  7958.         if(NOT STRING_IS_EMPTY(buffer))
  7959.             result = send(ufb->ufbfh,buffer,strlen(buffer),0);
  7960.         else
  7961.             result = 0;
  7962.     }
  7963.     else
  7964.     {
  7965.         result = vfprintf(out,fmt,args);
  7966.     }
  7967.  
  7968.     RETURN(result);
  7969.     return(result);
  7970. }
  7971.  
  7972. int
  7973. amiga_fprintf(FILE *out,const char *fmt,...)
  7974. {
  7975.     va_list args;
  7976.     int result;
  7977.  
  7978.     va_start(args,fmt);
  7979.     result = amiga_vfprintf(out,fmt,args);
  7980.     va_end(args);
  7981.  
  7982.     return(result);
  7983. }
  7984.  
  7985. int
  7986. amiga_printf(const char *fmt,...)
  7987. {
  7988.     va_list args;
  7989.     int result;
  7990.  
  7991.     va_start(args,fmt);
  7992.     result = amiga_vfprintf(stdout,fmt,args);
  7993.     va_end(args);
  7994.  
  7995.     return(result);
  7996. }
  7997.  
  7998. size_t
  7999. amiga_fwrite(const void *data,size_t blockSize,size_t numBlocks,FILE *out)
  8000. {
  8001.     struct UFB * ufb;
  8002.     size_t result;
  8003.  
  8004.     chkabort();
  8005.  
  8006.     ENTER();
  8007.  
  8008.     ufb = chkufb(fileno(out));
  8009.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8010.     {
  8011.         SHOWMSG("output to socket");
  8012.  
  8013.         result = send(ufb->ufbfh,(APTR)data,blockSize * numBlocks,0);
  8014.         if(result > 0)
  8015.             result = (result/blockSize);
  8016.     }
  8017.     else
  8018.     {
  8019.         result = fwrite(data,blockSize,numBlocks,out);
  8020.     }
  8021.  
  8022.     RETURN(result);
  8023.     return(result);
  8024. }
  8025.  
  8026. size_t
  8027. amiga_fread(void *data,size_t blockSize,size_t numBlocks,FILE *in)
  8028. {
  8029.     struct UFB * ufb;
  8030.     size_t result;
  8031.  
  8032.     chkabort();
  8033.  
  8034.     ENTER();
  8035.  
  8036.     ufb = chkufb(fileno(in));
  8037.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8038.     {
  8039.         SHOWMSG("input from socket");
  8040.  
  8041.         result = recv(ufb->ufbfh,(APTR)data,blockSize * numBlocks,0);
  8042.         if(result > 0)
  8043.             result = (result/blockSize);
  8044.     }
  8045.     else
  8046.     {
  8047.         result = fread(data,blockSize,numBlocks,in);
  8048.     }
  8049.  
  8050.     RETURN(result);
  8051.     return(result);
  8052. }
  8053.  
  8054. int
  8055. amiga_fclose(FILE * stream)
  8056. {
  8057.     struct UFB * ufb;
  8058.     int result;
  8059.  
  8060.     chkabort();
  8061.  
  8062.     ENTER();
  8063.  
  8064.     ufb = chkufb(fileno(stream));
  8065.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8066.         result = OK;
  8067.     else
  8068.         result = fclose(stream);
  8069.  
  8070.     RETURN(result);
  8071.     return(result);
  8072. }
  8073.  
  8074. int
  8075. amiga_fflush(FILE * stream)
  8076. {
  8077.     struct UFB * ufb;
  8078.     int result;
  8079.  
  8080.     chkabort();
  8081.  
  8082.     ENTER();
  8083.  
  8084.     ufb = chkufb(fileno(stream));
  8085.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8086.         result = OK;
  8087.     else
  8088.         result = fflush(stream);
  8089.  
  8090.     RETURN(result);
  8091.     return(result);
  8092. }
  8093.  
  8094. int
  8095. amiga_fseek(FILE * stream,long int offset,int mode)
  8096. {
  8097.     struct UFB * ufb;
  8098.     int result;
  8099.  
  8100.     chkabort();
  8101.  
  8102.     ENTER();
  8103.  
  8104.     ufb = chkufb(fileno(stream));
  8105.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8106.         result = OK;
  8107.     else
  8108.         result = fseek(stream,offset,mode);
  8109.  
  8110.     RETURN(result);
  8111.     return(result);
  8112. }
  8113.  
  8114. long int
  8115. amiga_ftell(FILE * stream)
  8116. {
  8117.     struct UFB * ufb;
  8118.     long int result;
  8119.  
  8120.     chkabort();
  8121.  
  8122.     ENTER();
  8123.  
  8124.     ufb = chkufb(fileno(stream));
  8125.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8126.         result = 0;
  8127.     else
  8128.         result = ftell(stream);
  8129.  
  8130.     RETURN(result);
  8131.     return(result);
  8132. }
  8133.  
  8134. /******************************************************************************/
  8135.  
  8136. int
  8137. amiga_setvbuf(FILE *stream,char *buff,int type,size_t size)
  8138. {
  8139.     struct UFB * ufb;
  8140.     int result;
  8141.  
  8142.     chkabort();
  8143.  
  8144.     ENTER();
  8145.  
  8146.     ufb = chkufb(fileno(stream));
  8147.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8148.         result = OK;
  8149.     else
  8150.         result = setvbuf(stream,buff,type,size);
  8151.  
  8152.     RETURN(result);
  8153.     return(result);
  8154. }
  8155.  
  8156. /******************************************************************************/
  8157.  
  8158. int
  8159. amiga_fputc(int c,FILE *stream)
  8160. {
  8161.     struct UFB * ufb;
  8162.     int result = ERROR;
  8163.  
  8164.     chkabort();
  8165.  
  8166.     ENTER();
  8167.  
  8168.     ufb = chkufb(fileno(stream));
  8169.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8170.     {
  8171.         UBYTE oneByte = c;
  8172.  
  8173.         if(send(ufb->ufbfh,&oneByte,1,0) > 0)
  8174.             result = OK;
  8175.     }
  8176.     else
  8177.     {
  8178.         result = fputc(c,stream);
  8179.     }
  8180.  
  8181.     RETURN(result);
  8182.     return(result);
  8183. }
  8184.  
  8185. /******************************************************************************/
  8186.  
  8187. VOID
  8188. amiga_setbuf(FILE *stream,char *buffer)
  8189. {
  8190.     struct UFB * ufb;
  8191.  
  8192.     chkabort();
  8193.  
  8194.     ENTER();
  8195.  
  8196.     ufb = chkufb(fileno(stream));
  8197.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8198.     {
  8199.         /* Do nothing */
  8200.     }
  8201.     else
  8202.     {
  8203.         setbuf(stream,buffer);
  8204.     }
  8205.  
  8206.     LEAVE();
  8207. }
  8208.  
  8209. /******************************************************************************/
  8210.  
  8211. int
  8212. amiga_recv(int fd,void *buff,size_t nbytes,int flags)
  8213. {
  8214.     struct UFB * ufb;
  8215.     int result = ERROR;
  8216.  
  8217.     ENTER();
  8218.  
  8219.     ufb = chkufb(fd);
  8220.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8221.         result = recv(ufb->ufbfh,buff,nbytes,flags);
  8222.     else
  8223.         errno = EBADF;
  8224.  
  8225.     RETURN(result);
  8226.     return(result);
  8227. }
  8228.  
  8229. /******************************************************************************/
  8230.  
  8231. int
  8232. amiga_send(int fd,void *buff,size_t nbytes,int flags)
  8233. {
  8234.     struct UFB * ufb;
  8235.     int result = ERROR;
  8236.  
  8237.     ENTER();
  8238.  
  8239.     ufb = chkufb(fd);
  8240.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8241.         result = send(ufb->ufbfh,buff,nbytes,flags);
  8242.     else
  8243.         errno = EBADF;
  8244.  
  8245.     RETURN(result);
  8246.     return(result);
  8247. }
  8248.  
  8249. /******************************************************************************/
  8250.  
  8251. int
  8252. amiga_smbrun(char *cmd,char *outfile,BOOL shared)
  8253. {
  8254.     struct MangleInfo mi_cmd;
  8255.     struct MangleInfo mi_outfile;
  8256.     int result = ERROR;
  8257.  
  8258.     ENTER();
  8259.  
  8260.     ForbidDOS();
  8261.  
  8262.     if(outfile == NULL)
  8263.         outfile = "/dev/null";
  8264.  
  8265.     if(MangleName(&cmd,&mi_cmd) == OK)
  8266.     {
  8267.         if(MangleName(&outfile,&mi_outfile) == OK)
  8268.         {
  8269.             BPTR in;
  8270.  
  8271.             in = Open("NIL:",MODE_OLDFILE);
  8272.             if(in != ZERO)
  8273.             {
  8274.                 BPTR out;
  8275.  
  8276.                 out = Open(outfile,MODE_NEWFILE);
  8277.                 if(out != ZERO)
  8278.                 {
  8279.                     if(SystemTags(cmd,
  8280.                         SYS_Input,        in,
  8281.                         SYS_Output,        out,
  8282.                         SYS_UserShell,    TRUE,
  8283.                         NP_WindowPtr,    NULL,
  8284.                     TAG_DONE) != -1)
  8285.                     {
  8286.                         result = OK;
  8287.                     }
  8288.                     else
  8289.                     {
  8290.                         MapIoErrToErrno();
  8291.                     }
  8292.  
  8293.                     Close(out);
  8294.                 }
  8295.                 else
  8296.                 {
  8297.                     MapIoErrToErrno();
  8298.                 }
  8299.  
  8300.                 Close(in);
  8301.             }
  8302.             else
  8303.             {
  8304.                 MapIoErrToErrno();
  8305.             }
  8306.  
  8307.             UnmangleName(&outfile,&mi_outfile);
  8308.         }
  8309.  
  8310.         UnmangleName(&cmd,&mi_cmd);
  8311.     }
  8312.  
  8313.     PermitDOS();
  8314.  
  8315.     RETURN(result);
  8316.     return(result);
  8317. }
  8318.  
  8319. /******************************************************************************/
  8320.  
  8321. #define IFBSIZE 1024
  8322. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  8323.  
  8324. int
  8325. amiga_get_interfaces(struct iface_struct * ifaces,int max_interfaces)
  8326. {
  8327.     struct ifreq * ifr_end;
  8328.     struct ifreq * ifr;
  8329.     struct ifconf * ifc;
  8330.     struct ifreq ifr_copy;
  8331.     int sockfd = -1;
  8332.     int result = -1;
  8333.     int total = 0;
  8334.     int len;
  8335.  
  8336.     /* Make room for the interface information. I hope
  8337.      * that 1024 bytes will be sufficient.
  8338.      */
  8339.     ifc = malloc(sizeof(*ifc) + IFBSIZE);
  8340.     if(ifc == NULL)
  8341.     {
  8342.         errno = ENOMEM;
  8343.         goto out;
  8344.     }
  8345.  
  8346.     sockfd = socket(AF_INET,SOCK_STREAM,0);
  8347.     if(sockfd < 0)
  8348.         goto out;
  8349.  
  8350.     /* Now attempt to copy the interface information into
  8351.      * the buffer. As of this writing, support for the
  8352.      * SIOCGIFCONF ioctl() action is undocumented in all
  8353.      * currently existing TCP/IP stacks. Nevertheless,
  8354.      * it appears to work.
  8355.      */
  8356.     ifc->ifc_len = IFBSIZE;
  8357.     ifc->ifc_buf = (char *)(ifc+1);
  8358.  
  8359.     if(IoctlSocket(sockfd,SIOCGIFCONF,(char *)ifc) != OK)
  8360.         goto out;
  8361.  
  8362.     len = ifc->ifc_len;
  8363.  
  8364.     ifr = (struct ifreq *)ifc->ifc_buf;
  8365.     ifr_end = (struct ifreq *)((char *)ifr + len);
  8366.  
  8367.     /* Now check each interface, extracting the interface
  8368.      * information.
  8369.      */
  8370.     while(ifr < ifr_end && total < max_interfaces)
  8371.     {
  8372.         ifr_copy = (*ifr);
  8373.  
  8374.         /* Try to obtain the address information. */
  8375.         if(IoctlSocket(sockfd,SIOCGIFADDR,(char *)&ifr_copy) == OK)
  8376.         {
  8377.             struct in_addr ipaddr;
  8378.  
  8379.             /* We need to remember this for later. */
  8380.             ipaddr = (*(struct sockaddr_in *)&ifr_copy.ifr_addr).sin_addr;
  8381.  
  8382.             /* And query the interface flags; in particular, we are interested
  8383.              * in whether this interface is currrently "up", i.e. "online".
  8384.              */
  8385.             if(IoctlSocket(sockfd,SIOCGIFFLAGS,(char *)&ifr_copy) == OK)
  8386.             {
  8387.                 if(ifr_copy.ifr_flags & IFF_UP)
  8388.                 {
  8389.                     /* And finally obtain the interface net mask. */
  8390.                     if(IoctlSocket(sockfd,SIOCGIFNETMASK,(char *)&ifr_copy) == OK)
  8391.                     {
  8392.                         struct in_addr nmask;
  8393.  
  8394.                         nmask = ((struct sockaddr_in *)&ifr_copy.ifr_addr)->sin_addr;
  8395.  
  8396.                         strncpy(ifaces[total].name, ifr_copy.ifr_name, sizeof(ifaces[total].name)-1);
  8397.                         ifaces[total].name[sizeof(ifaces[total].name)-1] = '\0';
  8398.  
  8399.                         ifaces[total].ip = ipaddr;
  8400.                         ifaces[total].netmask = nmask;
  8401.  
  8402.                         total++;
  8403.                     }
  8404.                 }
  8405.             }
  8406.         }
  8407.  
  8408.         len = max(sizeof(struct sockaddr),ifr->ifr_addr.sa_len);
  8409.         ifr = (struct ifreq *)(((char *)ifr) + sizeof(ifr->ifr_name) + len);
  8410.     }
  8411.  
  8412.     result = total;
  8413.  
  8414.  out:
  8415.  
  8416.     if(ifc != NULL)
  8417.         free(ifc);
  8418.  
  8419.     if(sockfd != -1)
  8420.         CloseSocket(sockfd);
  8421.  
  8422.     return(result);
  8423. }
  8424.  
  8425. /******************************************************************************/
  8426.  
  8427. FILE *
  8428. amiga_popen(const char * command,const char * mode)
  8429. {
  8430.     /* For now, nothing happens here. */
  8431.  
  8432.     errno = EPIPE;
  8433.  
  8434.     return(NULL);
  8435. }
  8436.  
  8437. int
  8438. amiga_pclose(FILE * fp)
  8439. {
  8440.     /* Almost twice as much happens here. */
  8441.     return(OK);
  8442. }
  8443. @
  8444.  
  8445.  
  8446. 1.15
  8447. log
  8448. @.
  8449. @
  8450. text
  8451. @d2 1
  8452. a2 1
  8453.  * $Id: amiga.c 1.14 2000/05/24 19:50:17 olsen Exp olsen $
  8454. d6 1
  8455. a6 1
  8456.  * AmigaOS wrapper routines for Samba 2.0.0, using the AmiTCP V4 API
  8457. d734 1
  8458. a734 1
  8459.     if(ufb != NULL)
  8460. d736 1
  8461. a736 3
  8462.         if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  8463.         {
  8464.             SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  8465. d738 1
  8466. a738 2
  8467.             CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  8468.         }
  8469. d953 1
  8470. a953 1
  8471.     SocketBase = OpenLibrary("bsdsocket.library",4);
  8472. d1042 1
  8473. a1042 1
  8474.             ReportProblem("Error opening \"bsdsocket.library\" V4.");
  8475. d2775 1
  8476. a2775 1
  8477.     if(ufb != NULL)
  8478. @
  8479.  
  8480.  
  8481. 1.14
  8482. log
  8483. @.
  8484. @
  8485. text
  8486. @d2 1
  8487. a2 1
  8488.  * $Id: amiga.c 1.13 1999/12/25 11:31:10 olsen Exp olsen $
  8489. d37 1
  8490. d286 9
  8491. a294 1
  8492. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && (fib)->fib_DirEntryType != ST_SOFTLINK)
  8493. d311 7
  8494. d340 7
  8495. d558 1
  8496. a558 1
  8497.             if(reqWindow != NULL)
  8498. d948 1
  8499. d1058 37
  8500. d1155 2
  8501. d1162 2
  8502. d1169 2
  8503. d1182 2
  8504. d1189 2
  8505. d1196 2
  8506. d1203 2
  8507. d1210 2
  8508. d1218 2
  8509. d1236 2
  8510. d1252 2
  8511. d1295 2
  8512. d1300 1
  8513. d1357 2
  8514. a1358 1
  8515.         for(i = 0 ; i < strlen(name)-1 ; i++)
  8516. d1411 1
  8517. d1436 1
  8518. d1442 2
  8519. d1459 1
  8520. a1459 1
  8521.                 struct FileInfoBlock __aligned fib;
  8522. d1461 1
  8523. a1461 1
  8524.                 if(Examine(fileLock,&fib))
  8525. d1470 2
  8526. a1471 2
  8527.                     len = strlen(fib.fib_FileName);
  8528.                     if(strlen(file_name) > len && Strnicmp(file_name,fib.fib_FileName,len) == SAME)
  8529. d1583 1
  8530. a1583 1
  8531.             struct FileInfoBlock __aligned fib;
  8532. d1585 1
  8533. a1585 1
  8534.             if(Examine(fileLock,&fib))
  8535. d1593 1
  8536. a1593 1
  8537.                 if(FIB_IS_FILE(&fib))
  8538. d1637 1
  8539. a1637 1
  8540.             for(i = strlen(parentDirName)-1 ; i >= 0 ; i--)
  8541. d1685 1
  8542. a1685 1
  8543.                                     struct FileInfoBlock __aligned fib;
  8544. d1687 1
  8545. a1687 1
  8546.                                     if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8547. d1690 1
  8548. a1690 1
  8549.                                         if(Stricmp(fib.fib_FileName,FilePart(name)) == SAME)
  8550. d1820 1
  8551. a1820 1
  8552.             struct FileInfoBlock __aligned fib;
  8553. d1822 1
  8554. a1822 1
  8555.             if(Examine(drawerLock,&fib))
  8556. d1825 1
  8557. a1825 1
  8558.                 if(FIB_IS_DRAWER(&fib))
  8559. d1945 2
  8560. d1957 3
  8561. d1991 1
  8562. a1991 1
  8563.                 result = &odn->odn_DIR;
  8564. d2003 1
  8565. a2003 1
  8566.                         struct InfoData __aligned id;
  8567. d2005 2
  8568. a2006 2
  8569.                         /* Is there a disk present? */
  8570.                         if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  8571. d2008 1
  8572. a2008 2
  8573.                             STRPTR name = BADDR(dol->dol_Name);
  8574.                             struct Node * node;
  8575. d2010 4
  8576. a2013 5
  8577.                             /* Collect the number of blocks used and
  8578.                              * available in our fake root directory.
  8579.                              * Not that it matters much...
  8580.                              */
  8581.                             if(id.id_BytesPerBlock == 512)
  8582. d2015 6
  8583. a2020 2
  8584.                                 RootBlocks        += id.id_NumBlocks;
  8585.                                 RootBlocksUsed    += id.id_NumBlocksUsed;
  8586. d2024 2
  8587. a2025 2
  8588.                                 RootBlocks        += (id.id_NumBlocks * id.id_BytesPerBlock) / 512;
  8589.                                 RootBlocksUsed    += (id.id_NumBlocksUsed * id.id_BytesPerBlock) / 512;
  8590. d2027 7
  8591. d2035 20
  8592. a2054 2
  8593.                             node = malloc(sizeof(*node) + ((int)name[0])+1);
  8594.                             if(node != NULL)
  8595. d2056 17
  8596. a2072 4
  8597.                                 /* Copy the name of the volume. */
  8598.                                 node->ln_Name = (char *)(node + 1);
  8599.                                 strncpy(node->ln_Name,&name[1],name[0]);
  8600.                                 node->ln_Name[ name[0] ] = '\0';
  8601. d2078 2
  8602. d2082 3
  8603. a2085 2
  8604.  
  8605.                     dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  8606. a2086 2
  8607.  
  8608.                 UnLockDosList(LDF_VOLUMES|LDF_READ);
  8609. d2177 4
  8610. d2188 2
  8611. d2192 1
  8612. a2192 1
  8613.         struct OpenDirNode * odn = (struct OpenDirNode *)dir->dd_buf;
  8614. d2194 1
  8615. d2210 2
  8616. d2219 2
  8617. d2225 1
  8618. a2225 1
  8619.         struct OpenDirNode * odn = (struct OpenDirNode *)dir->dd_buf;
  8620. d2227 1
  8621. d2234 2
  8622. d2241 2
  8623. d2257 2
  8624. d2276 2
  8625. d2280 2
  8626. d2295 2
  8627. d2310 2
  8628. d2320 1
  8629. d2335 1
  8630. d2340 2
  8631. d2356 1
  8632. d2368 2
  8633. d2394 2
  8634. a2395 2
  8635.         if(CurrentDirName[strlen(CurrentDirName)-1] != '/' &&
  8636.            CurrentDirName[strlen(CurrentDirName)-1] != ':' &&
  8637. d2428 1
  8638. d2497 1
  8639. a2497 1
  8640.             struct FileInfoBlock __aligned fib;
  8641. d2499 1
  8642. a2499 1
  8643.             if(Examine(fileLock,&fib))
  8644. d2507 1
  8645. a2507 1
  8646.                 if(FIB_IS_DRAWER(&fib))
  8647. d3843 1
  8648. a3843 1
  8649.                     struct FileInfoBlock __aligned fib;
  8650. d3845 1
  8651. a3845 1
  8652.                     if(Examine(fileLock,&fib))
  8653. d3870 8
  8654. a3877 8
  8655.                             fib.fib_Protection = FIBF_OTR_READ |
  8656.                                                  FIBF_OTR_WRITE |
  8657.                                                  FIBF_OTR_EXECUTE |
  8658.                                                  FIBF_OTR_DELETE |
  8659.                                                  FIBF_GRP_READ |
  8660.                                                  FIBF_GRP_WRITE |
  8661.                                                  FIBF_GRP_EXECUTE |
  8662.                                                  FIBF_GRP_DELETE;
  8663. d3880 1
  8664. a3880 1
  8665.                         ConvertFileInfoToStat(((struct FileLock *)BADDR(fileLock))->fl_Task,&fib,st);
  8666. d3906 1
  8667. a3906 1
  8668.                             struct FileInfoBlock __aligned fib;
  8669. d3908 1
  8670. a3908 1
  8671.                             if(Examine(parentLock,&fib))
  8672. d3912 1
  8673. a3912 1
  8674.                                 while(ExNext(parentLock,&fib))
  8675. d3914 1
  8676. a3914 1
  8677.                                     if(Stricmp(fib.fib_FileName,onlyFileName) == SAME)
  8678. d3916 1
  8679. a3916 1
  8680.                                         ConvertFileInfoToStat(((struct FileLock *)BADDR(parentLock))->fl_Task,&fib,st);
  8681. d4026 1
  8682. a4026 1
  8683.                 struct FileInfoBlock __aligned fib;
  8684. d4030 1
  8685. a4030 1
  8686.                 if(ExamineFH(ufb->ufbfh,&fib))
  8687. d4032 1
  8688. a4032 1
  8689.                     ConvertFileInfoToStat(fileHandle->fh_Type,&fib,st);
  8690. d4290 5
  8691. d4330 2
  8692. a4331 1
  8693.                 char __aligned newName[MAX_BSTR_LEN];
  8694. d4333 6
  8695. a4338 2
  8696.                 newName[0] = strlen(name);
  8697.                 strncpy(&newName[1],name,newName[0]);
  8698. d4629 5
  8699. a4633 1
  8700.     result = getgid();
  8701. d4833 4
  8702. a4836 1
  8703.     result = getuid();
  8704. a4867 1
  8705.  
  8706. d5149 3
  8707. a5151 1
  8708.             struct InfoData __aligned id;
  8709. d5153 4
  8710. a5156 2
  8711.             /* Is there a disk present? */
  8712.             if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  8713. d5158 4
  8714. a5161 10
  8715.                 STRPTR name = BADDR(dol->dol_Name);
  8716.                 struct Node * node;
  8717.  
  8718.                 node = malloc(sizeof(*node) + ((int)name[0])+1);
  8719.                 if(node != NULL)
  8720.                 {
  8721.                     /* Copy the name of the volume. */
  8722.                     node->ln_Name = (char *)(node + 1);
  8723.                     strncpy(node->ln_Name,&name[1],name[0]);
  8724.                     node->ln_Name[ name[0] ] = '\0';
  8725. d5163 1
  8726. a5163 2
  8727.                     AddTail(list,node);
  8728.                 }
  8729. d5171 32
  8730. d5220 1
  8731. a5220 1
  8732.             struct FileInfoBlock __aligned fib;
  8733. d5222 1
  8734. a5222 1
  8735.             if(Examine(dirLock,&fib))
  8736. d5236 1
  8737. a5475 1
  8738.  
  8739. d5509 1
  8740. a5509 1
  8741.                             struct FileInfoBlock __aligned fib;
  8742. d5511 1
  8743. a5511 1
  8744.                             if(Examine(dirLock,&fib))
  8745. d5515 1
  8746. a5515 1
  8747.                                 while(ExNext(dirLock,&fib))
  8748. d5517 1
  8749. a5517 1
  8750.                                     D(("checking '%s'",fib.fib_FileName));
  8751. d5519 1
  8752. a5519 1
  8753.                                     if(do_match(fib.fib_FileName,whichPattern))
  8754. d5523 1
  8755. a5523 1
  8756.                                         if(fprintf(out,"%s\n",fib.fib_FileName) < 0)
  8757. a5583 1
  8758.         struct List list;
  8759. a5585 2
  8760.         NewList(&list);
  8761.  
  8762. d5688 2
  8763. d5692 1
  8764. d6205 1
  8765. a6205 1
  8766.                     struct InfoData __aligned id;
  8767. d6207 1
  8768. a6207 1
  8769.                     if(Info(fileLock,&id))
  8770. d6212 2
  8771. a6213 2
  8772.                         if(id.id_NumBlocks == 0)
  8773.                             id.id_NumBlocks = 1;
  8774. d6215 2
  8775. a6216 2
  8776.                         if(id.id_BytesPerBlock == 0)
  8777.                             id.id_BytesPerBlock = 512;
  8778. d6218 3
  8779. a6220 3
  8780.                         f->f_fsize    = id.id_BytesPerBlock;                        /* fundamental file system block size */
  8781.                         f->f_blocks    = id.id_NumBlocks;                            /* total data blocks in file system */
  8782.                         f->f_bfree    = id.id_NumBlocks - id.id_NumBlocksUsed;    /* free blocks in fs */
  8783. d6689 2
  8784. d6694 17
  8785. a6711 3
  8786.  
  8787.             /* Register this program with a new process ID. */
  8788.             scn->scn_PID = SambaSemaphore->ss_PID++;
  8789. a6712 1
  8790.  
  8791. d6900 1
  8792. a6900 1
  8793.     struct FileInfoBlock __aligned fib;
  8794. d6907 1
  8795. a6907 1
  8796.     if(ExamineFH(fileHandle,&fib))
  8797. d6911 1
  8798. a6911 1
  8799.         fln = AllocVec(sizeof(*fln) + strlen(fib.fib_FileName),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  8800. d6917 1
  8801. a6917 1
  8802.                 strcpy(fln->fln_FileName,fib.fib_FileName);
  8803. d6960 1
  8804. a6960 1
  8805.         struct FileInfoBlock __aligned this_fib;
  8806. d6962 1
  8807. a6962 1
  8808.         if(ExamineFH(fileHandle,&this_fib))
  8809. d6986 1
  8810. a6986 1
  8811.                     if(Stricmp(fln->fln_FileName,this_fib.fib_FileName) == SAME)
  8812. d7200 1
  8813. a7200 1
  8814.                 struct FileInfoBlock __aligned fib;
  8815. d7219 2
  8816. a7220 2
  8817.                             if(ExamineFH(fileHandle,&fib))
  8818.                                 len = fib.fib_Size - start;
  8819. d7240 2
  8820. a7241 2
  8821.                                 if(ExamineFH(fileHandle,&fib))
  8822.                                     len = fib.fib_Size - start;
  8823. d7260 1
  8824. a7260 1
  8825.                         if(ExamineFH(fileHandle,&fib))
  8826. d7262 1
  8827. a7262 1
  8828.                             start = fib.fib_Size + l->l_start;
  8829. d7265 1
  8830. a7265 1
  8831.                                 len = fib.fib_Size - start;
  8832. d7308 1
  8833. a7308 1
  8834.                                     struct FileInfoBlock __aligned fib;
  8835. d7310 1
  8836. a7310 1
  8837.                                     if(ExamineFH(fileHandle,&fib))
  8838. d7332 1
  8839. a7332 1
  8840.                                             FindFileLockNodeByDrawerAndName(parentDir,fib.fib_FileName,&existing_fln);
  8841. @
  8842.  
  8843.  
  8844. 1.13
  8845. log
  8846. @.
  8847. @
  8848. text
  8849. @d2 1
  8850. a2 1
  8851.  * $Id: amiga.c 1.12 1999/12/01 09:47:07 olsen Exp olsen $
  8852. d9 1
  8853. a9 1
  8854.  * Copyright (C) 1999 by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>
  8855. d1372 1
  8856. d1380 1
  8857. a1380 1
  8858.                     if(strlen((STRPTR)name) > len && Strnicmp((STRPTR)name,fib.fib_FileName,len) == SAME)
  8859. d8081 19
  8860. @
  8861.  
  8862.  
  8863. 1.12
  8864. log
  8865. @.
  8866. @
  8867. text
  8868. @d2 1
  8869. a2 1
  8870.  * $Id: amiga.c 1.11 1999/11/06 16:03:15 olsen Exp olsen $
  8871. d7993 3
  8872. d8007 6
  8873. d8024 3
  8874. d8031 1
  8875. d8036 1
  8876. d8039 3
  8877. d8046 1
  8878. @
  8879.  
  8880.  
  8881. 1.11
  8882. log
  8883. @.
  8884. @
  8885. text
  8886. @d2 1
  8887. a2 1
  8888.  * $Id: amiga.c 1.10 1999/10/16 09:15:58 olsen Exp olsen $
  8889. d56 2
  8890. d85 5
  8891. d7973 88
  8892. @
  8893.  
  8894.  
  8895. 1.10
  8896. log
  8897. @.
  8898. @
  8899. text
  8900. @d2 1
  8901. a2 1
  8902.  * $Id: amiga.c 1.9 1999/08/09 15:28:43 olsen Exp olsen $
  8903. d36 1
  8904. d100 1
  8905. a100 1
  8906. STATIC int MangleName(char **namePtr, struct MangleInfo *mi);
  8907. d291 1
  8908. d1337 3
  8909. a1339 2
  8910.         /* Now check if the file name is longer than 30
  8911.          * characters. This is to avoid name space clashes.
  8912. d1341 1
  8913. a1341 1
  8914.         if(strlen(FilePart((STRPTR)name)) > 30)
  8915. d1343 61
  8916. a1403 2
  8917.             errno = ENAMETOOLONG; /* name is too long for us */
  8918.             goto out;
  8919. d4940 174
  8920. d5205 2
  8921. a5206 3
  8922.         char whichPatternBuffer[MAX_FILENAME_LEN];
  8923.         char *whichPattern = whichPatternBuffer;
  8924.         BOOL oldAllowBreak = AllowBreak;
  8925. d5208 1
  8926. a5208 2
  8927.         /* We don't want to be interrupted. */
  8928.         AllowBreak = FALSE;
  8929. d5210 5
  8930. a5214 2
  8931.         /* Now find the pattern to use. */
  8932.         nstrcpy_blank(sizeof(whichPatternBuffer),whichPattern,options);
  8933. d5216 2
  8934. a5217 3
  8935.         SHOWMSG("doing `ls'");
  8936.         SHOWSTRING(whichPattern);
  8937.         SHOWSTRING(redirectionFile);
  8938. d5219 2
  8939. a5220 5
  8940.         /* What happens next is that the contents of the
  8941.          * current directory are scanned. All file names
  8942.          * that match the given pattern are stored in the
  8943.          * redirection file.
  8944.          */
  8945. d5222 3
  8946. a5224 3
  8947.         if(MangleName(&redirectionFile,&mi) == OK)
  8948.         {
  8949.             FILE * out;
  8950. d5226 5
  8951. a5230 1
  8952.             ForbidDOS();
  8953. d5232 1
  8954. a5232 2
  8955.             out = fopen(redirectionFile,"wb");
  8956.             if(out != NULL)
  8957. d5234 1
  8958. a5234 1
  8959.                 BPTR dirLock;
  8960. d5236 4
  8961. a5239 2
  8962.                 dirLock = Lock("",SHARED_LOCK);
  8963.                 if(dirLock != ZERO)
  8964. d5241 31
  8965. a5271 1
  8966.                     struct FileInfoBlock __aligned fib;
  8967. d5273 4
  8968. a5276 1
  8969.                     if(Examine(dirLock,&fib))
  8970. d5278 1
  8971. a5278 1
  8972.                         BOOL stopped = FALSE;
  8973. d5280 4
  8974. a5283 1
  8975.                         while(ExNext(dirLock,&fib))
  8976. d5285 3
  8977. a5287 1
  8978.                             if(FIB_IS_FILE(&fib))
  8979. d5289 3
  8980. a5291 1
  8981.                                 if(do_match(fib.fib_FileName,whichPattern))
  8982. d5293 3
  8983. a5295 1
  8984.                                     if(fprintf(out,"%s\n",fib.fib_FileName) < 0)
  8985. d5297 11
  8986. a5307 2
  8987.                                         stopped = TRUE;
  8988.                                         break;
  8989. a5309 2
  8990.                             }
  8991.                         }
  8992. d5311 3
  8993. a5313 3
  8994.                         if(NOT stopped)
  8995.                         {
  8996.                             LONG error = IoErr();
  8997. d5315 10
  8998. a5324 3
  8999.                             if(error == ERROR_NO_MORE_ENTRIES)
  9000.                             {
  9001.                                 result = OK;
  9002. a5327 1
  9003.                                 SetIoErr(error);
  9004. d5330 6
  9005. a5337 4
  9006.                     else
  9007.                     {
  9008.                         MapIoErrToErrno();
  9009.                     }
  9010. d5339 4
  9011. a5342 5
  9012.                     UnLock(dirLock);
  9013.                 }
  9014.                 else
  9015.                 {
  9016.                     MapIoErrToErrno();
  9017. d5345 1
  9018. a5345 1
  9019.                 fclose(out);
  9020. d5347 1
  9021. a5347 2
  9022.                 if(result != OK)
  9023.                     DeleteFile(redirectionFile);
  9024. d5350 1
  9025. a5350 3
  9026.             PermitDOS();
  9027.  
  9028.             UnmangleName(&cmd,&mi);
  9029. a5351 2
  9030.  
  9031.         AllowBreak = oldAllowBreak;
  9032. d5360 4
  9033. d5456 2
  9034. a5457 2
  9035.                 struct MangleInfo mi;
  9036.                 BOOL hasDot;
  9037. d5459 1
  9038. a5459 1
  9039.                 hasDot = (BOOL)(strncmp(whichDrawer,"./",2) == SAME || strcmp(whichDrawer,".") == SAME);
  9040. d5461 1
  9041. a5461 1
  9042.                 if(MangleName(&whichDrawer,&mi) == OK)
  9043. d5463 1
  9044. a5463 1
  9045.                     BPTR dirLock;
  9046. d5465 1
  9047. a5465 2
  9048.                     dirLock = Lock(whichDrawer,SHARED_LOCK);
  9049.                     if(dirLock != ZERO)
  9050. d5467 1
  9051. a5467 1
  9052.                         struct FileInfoBlock __aligned fib;
  9053. d5469 3
  9054. a5471 1
  9055.                         if(Examine(dirLock,&fib))
  9056. d5473 3
  9057. a5475 8
  9058.                             struct AnchorPath * ap;
  9059.  
  9060.                             ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9061.                             if(ap != NULL)
  9062.                             {
  9063.                                 BOOL stopped = FALSE;
  9064.                                 BPTR oldDir;
  9065.                                 LONG error;
  9066. d5477 1
  9067. a5477 1
  9068.                                 oldDir = CurrentDir(dirLock);
  9069. d5479 3
  9070. a5481 75
  9071.                                 memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9072.                                 ap->ap_Strlen        = MAX_FILENAME_LEN;
  9073.                                 ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9074.  
  9075.                                 if((error = MatchFirst("",ap)) == OK)
  9076.                                 {
  9077.                                     do
  9078.                                     {
  9079.                                         D(("checking |%s|",ap->ap_Buf));
  9080.  
  9081.                                         if(FIB_IS_FILE(&ap->ap_Info))
  9082.                                         {
  9083.                                             SHOWMSG("this is a file");
  9084.                                             SHOWSTRING(ap->ap_Info.fib_FileName);
  9085.  
  9086.                                             if(do_match(ap->ap_Info.fib_FileName,whichPattern))
  9087.                                             {
  9088.                                                 D(("Output |%s/%s|",whichDrawerBuffer,ap->ap_Buf));
  9089.                                                 if(fprintf(out,"%s%s/%s\n",(hasDot) ? "./" : "",whichDrawerBuffer,ap->ap_Buf) < 0)
  9090.                                                 {
  9091.                                                     stopped = TRUE;
  9092.                                                     break;
  9093.                                                 }
  9094.                                             }
  9095.                                             else
  9096.                                             {
  9097.                                                 SHOWMSG("but its name does not match");
  9098.                                             }
  9099.                                         }
  9100.                                         else
  9101.                                         {
  9102.                                             SHOWMSG("this is a drawer");
  9103.  
  9104.                                             if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  9105.                                                 SET_FLAG(ap->ap_Flags,APF_DODIR);
  9106.                                             else
  9107.                                                 CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  9108.                                         }
  9109.                                     }
  9110.                                     while((error = MatchNext(ap)) == OK);
  9111.                                 }
  9112.  
  9113.                                 MatchEnd(ap);
  9114.  
  9115.                                 CurrentDir(oldDir);
  9116.  
  9117.                                 if(NOT stopped)
  9118.                                 {
  9119.                                     if(error == ERROR_NO_MORE_ENTRIES)
  9120.                                     {
  9121.                                         result = OK;
  9122.                                     }
  9123.                                     else if(error == ERROR_BREAK)
  9124.                                     {
  9125.                                         /* Don't do anything; we are going
  9126.                                          * to delete the file anyway.
  9127.                                          */
  9128.                                     }
  9129.                                     else
  9130.                                     {
  9131.                                         SetIoErr(error);
  9132.                                         MapIoErrToErrno();
  9133.                                     }
  9134.                                 }
  9135.  
  9136.                                 free(ap);
  9137.                             }
  9138.                             else
  9139.                             {
  9140.                                 errno = ENOMEM;
  9141.                             }
  9142.                         }
  9143.                         else
  9144.                         {
  9145.                             MapIoErrToErrno();
  9146. d5484 2
  9147. a5485 1
  9148.                         UnLock(dirLock);
  9149. d5489 3
  9150. a5491 1
  9151.                         MapIoErrToErrno();
  9152. a5492 2
  9153.  
  9154.                     UnmangleName(&whichDrawer,&mi);
  9155. d7894 70
  9156. @
  9157.  
  9158.  
  9159. 1.9
  9160. log
  9161. @.
  9162. @
  9163. text
  9164. @d2 1
  9165. a2 1
  9166.  * $Id: amiga.c 1.8 1999/05/21 09:38:15 olsen Exp olsen $
  9167. d315 10
  9168. d326 30
  9169. a355 1
  9170. char * VersionTag = VERSTAG " Samba version 2.0.0 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  9171. d5164 3
  9172. d5208 1
  9173. a5208 1
  9174.                                                 if(fprintf(out,"%s/%s\n",whichDrawerBuffer,ap->ap_Buf) < 0)
  9175. a5964 2
  9176. #define SEEK_ERROR (-1)
  9177.  
  9178. a5980 1
  9179.     {
  9180. a5981 55
  9181.  
  9182.         /* Now comes the tricky bit; check if the lseek() call
  9183.          * was meant to *extend* the file.
  9184.          */
  9185.         if(result != OK)
  9186.         {
  9187.             struct FileInfoBlock __aligned fib;
  9188.  
  9189.             if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  9190.             {
  9191.                 off_t new_offset = 0;
  9192.                 BOOL good = FALSE;
  9193.  
  9194.                 switch(mode)
  9195.                 {
  9196.                     case SEEK_SET:
  9197.  
  9198.                         new_offset = offset;
  9199.                         good = TRUE;
  9200.                         break;
  9201.  
  9202.                     case SEEK_CUR:
  9203.  
  9204.                         new_offset = Seek((BPTR)ufb->ufbfh,0,OFFSET_CURRENT);
  9205.                         if(new_offset != SEEK_ERROR)
  9206.                         {
  9207.                             new_offset += offset;
  9208.                             good = TRUE;
  9209.                         }
  9210.  
  9211.                         break;
  9212.  
  9213.                     case SEEK_END:
  9214.  
  9215.                         new_offset = fib.fib_Size + offset;
  9216.                         good = TRUE;
  9217.                         break;
  9218.                 }
  9219.  
  9220.                 if(good)
  9221.                 {
  9222.                     if(new_offset > fib.fib_Size)
  9223.                     {
  9224.                         /* Make the file larger; according to the BSD
  9225.                          * documentation, we should fill the newly
  9226.                          * allocated file area with zeroes. I'm not
  9227.                          * sure whether this belongs here.
  9228.                          */
  9229.                         if(SetFileSize((BPTR)ufb->ufbfh,new_offset,OFFSET_BEGINNING) != SET_FILESIZE_ERROR)
  9230.                             result = lseek(fd,offset,mode);
  9231.                     }
  9232.                 }
  9233.             }
  9234.         }
  9235.     }
  9236. a5982 1
  9237.     {
  9238. a5983 1
  9239.     }
  9240. d7047 1
  9241. a7047 1
  9242.                                 ObtainSemaphoreShared((struct SignalSemaphore *)SambaSemaphore);
  9243. @
  9244.  
  9245.  
  9246. 1.8
  9247. log
  9248. @.
  9249. @
  9250. text
  9251. @d2 1
  9252. a2 1
  9253.  * $Id: amiga.c 1.7 1999/05/02 10:45:08 olsen Exp olsen $
  9254. a216 2
  9255. VOID _CXOVF(VOID);
  9256. VOID __regargs _CXBRK(VOID);
  9257. a275 1
  9258. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType > 0)
  9259. d277 1
  9260. d316 1
  9261. a316 1
  9262. char * VersionTag = VERSTAG " Samba version 2.0.3 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  9263. d7657 40
  9264. @
  9265.  
  9266.  
  9267. 1.7
  9268. log
  9269. @.
  9270. @
  9271. text
  9272. @d2 1
  9273. a2 1
  9274.  * $Id: amiga.c 1.6 1999/02/28 09:16:53 olsen Exp olsen $
  9275. d34 1
  9276. d1793 1
  9277. a1793 3
  9278.  
  9279.                 /* Is there a filing system mounted here? */
  9280.                 while(dol != NULL && dol->dol_Task != NULL)
  9281. d1795 4
  9282. a1798 4
  9283.                     struct InfoData __aligned id;
  9284.  
  9285.                     /* Is there a disk present? */
  9286.                     if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  9287. d1800 1
  9288. a1800 2
  9289.                         char *name = BADDR(dol->dol_Name);
  9290.                         struct Node * node;
  9291. d1802 2
  9292. a1803 5
  9293.                         /* Collect the number of blocks used and
  9294.                          * available in our fake root directory.
  9295.                          * Not that it matters much...
  9296.                          */
  9297.                         if(id.id_BytesPerBlock == 512)
  9298. d1805 17
  9299. a1821 8
  9300.                             RootBlocks        += id.id_NumBlocks;
  9301.                             RootBlocksUsed    += id.id_NumBlocksUsed;
  9302.                         }
  9303.                         else
  9304.                         {
  9305.                             RootBlocks        += (id.id_NumBlocks * id.id_BytesPerBlock) / 512;
  9306.                             RootBlocksUsed    += (id.id_NumBlocksUsed * id.id_BytesPerBlock) / 512;
  9307.                         }
  9308. d1823 7
  9309. a1829 7
  9310.                         node = malloc(sizeof(*node) + name[0]+1);
  9311.                         if(node != NULL)
  9312.                         {
  9313.                             /* Copy the name of the volume. */
  9314.                             node->ln_Name = (char *)(node + 1);
  9315.                             strncpy(node->ln_Name,&name[1],name[0]);
  9316.                             node->ln_Name[ name[0] ] = '\0';
  9317. d1831 1
  9318. a1831 1
  9319.                             AddTail(&odn->odn_VolumeList,node);
  9320. d1833 3
  9321. a1835 2
  9322.                             if(odn->odn_NextNode == NULL)
  9323.                                 odn->odn_NextNode = node;
  9324. d2338 1
  9325. a2338 1
  9326.      * it is first removed.Both <from> and <to> must be of the same type (that is,
  9327. d2471 1
  9328. a2471 1
  9329.     
  9330. d5957 1
  9331. a5957 1
  9332.     
  9333. d5961 1
  9334. a5961 1
  9335.     
  9336. d5965 1
  9337. a5965 1
  9338.     
  9339. d5967 1
  9340. a5967 1
  9341.     
  9342. d5976 1
  9343. a5976 1
  9344.     
  9345. d5978 1
  9346. a5978 1
  9347.     
  9348. d5983 1
  9349. a5983 1
  9350.     
  9351. @
  9352.  
  9353.  
  9354. 1.6
  9355. log
  9356. @.
  9357. @
  9358. text
  9359. @d2 1
  9360. a2 1
  9361.  * $Id: amiga.c 1.5 1999/02/22 15:31:18 olsen Exp olsen $
  9362. d81 1
  9363. d316 2
  9364. a317 2
  9365. #include "Amiga_Samba_2.0.0_rev.h"
  9366. char * VersionTag = VERSTAG " Ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  9367. d473 1
  9368. d487 74
  9369. a560 1
  9370.             EasyRequestArgs(NULL,&es,NULL,(APTR)varArgs);
  9371. d987 1
  9372. a987 1
  9373.     /* Initialize up the current time zone variable. */
  9374. d1170 2
  9375. a1171 1
  9376.             if(name[i] == '.')
  9377. d2332 6
  9378. d2343 65
  9379. a2407 1
  9380.             result = rename(old,new);
  9381. d2412 4
  9382. d2419 4
  9383. a2433 1
  9384.     BPTR oldDir;
  9385. d2443 1
  9386. a2443 5
  9387.     ForbidDOS();
  9388.  
  9389.     oldDir = CurrentDir(ZERO);
  9390.  
  9391.     if(NameFromLock(oldDir,buf,size))
  9392. d2445 3
  9393. a2447 2
  9394.         if(MapFileNameAmigaToUnix(buf,buf,size) == OK)
  9395.             result = buf;
  9396. d2451 5
  9397. a2455 2
  9398.         MapIoErrToErrno();
  9399.     }
  9400. d2457 11
  9401. a2467 1
  9402.     CurrentDir(oldDir);
  9403. d2469 2
  9404. a2470 1
  9405.     PermitDOS();
  9406. d3538 1
  9407. a3538 1
  9408.                 /* Nobody can write to this "directory". */
  9409. d3610 42
  9410. a3651 1
  9411.                     MapIoErrToErrno();
  9412. d3853 1
  9413. d3855 1
  9414. d3857 18
  9415. a3874 1
  9416.             MapIoErrToErrno();
  9417. d4024 1
  9418. a4024 1
  9419.         /* AmigaDOS 3.0 and up has a SetOwner() call. */
  9420. d4168 1
  9421. d4170 1
  9422. d4172 18
  9423. a4189 1
  9424.             MapIoErrToErrno();
  9425. d4769 1
  9426. a4769 1
  9427.             /* Look for a character matching  the one after the '*' */
  9428. d4805 1
  9429. a4805 1
  9430.     if((*p) == '\0' && str[0] == '.' && str[1] == 0)
  9431. d4941 6
  9432. d5102 10
  9433. d5140 1
  9434. d5143 2
  9435. d5189 2
  9436. d5920 2
  9437. d5933 2
  9438. d5938 1
  9439. d5940 55
  9440. d5996 1
  9441. d5998 3
  9442. d6179 1
  9443. a6179 1
  9444. STATIC STRPTR SambaSemaphoreName = "Amiga Samba 2.0.0";
  9445. d6725 1
  9446. a6725 1
  9447.      * This means for example, that every unlock request must
  9448. d7266 2
  9449. d7287 1
  9450. @
  9451.  
  9452.  
  9453. 1.5
  9454. log
  9455. @.
  9456. @
  9457. text
  9458. @d2 1
  9459. a2 1
  9460.  * $Id: amiga.c 1.4 1999/02/21 10:58:42 olsen Exp olsen $
  9461. d868 1
  9462. d891 4
  9463. a4607 2
  9464.     PUSH_ALL();
  9465.  
  9466. a4993 1
  9467.     POP();
  9468. d6044 3
  9469. d6051 1
  9470. d6068 3
  9471. d6133 4
  9472. d6183 4
  9473. d6211 3
  9474. d6254 4
  9475. d6299 5
  9476. d6308 1
  9477. d6311 3
  9478. d6316 5
  9479. a6320 1
  9480.                 if(NOT shared && NOT lrn->lrn_Shared && lrn->lrn_Owner == ThisClient->scn_PID)
  9481. d6323 3
  9482. d6340 4
  9483. a6349 2
  9484.         PUSH_ALL();
  9485.  
  9486. a6382 2
  9487.  
  9488.         POP();
  9489. d6393 12
  9490. a6404 3
  9491.     PUSH_ALL();
  9492.  
  9493.     /* Check for proper input. */
  9494. d6565 1
  9495. a6565 1
  9496.                                                 SHOWMSG("that file is already locked by someone else");
  9497. d6598 3
  9498. d6607 13
  9499. a6619 1
  9500.                                                 Delay(TICKS_PER_SECOND / 2);
  9501. a6833 2
  9502.     POP();
  9503.  
  9504. d7278 1
  9505. a7278 1
  9506.     int result;
  9507. @
  9508.  
  9509.  
  9510. 1.4
  9511. log
  9512. @.
  9513. @
  9514. text
  9515. @d2 1
  9516. a2 1
  9517.  * $Id: amiga.c 1.3 1999/02/20 17:52:48 olsen Exp olsen $
  9518. d98 1
  9519. a98 1
  9520. STATIC VOID CloseUnlinkCleanup(VOID);
  9521. d104 2
  9522. a108 1
  9523. STATIC int LockTheFile(int cmd, struct flock *l, struct UFB *ufb);
  9524. d114 10
  9525. d284 1
  9526. d322 10
  9527. d335 1
  9528. a335 1
  9529.     if(AllowBreak && FLAG_IS_SET(SetSignal(0,SIGBREAKF_CTRL_C),SIGBREAKF_CTRL_C))
  9530. d926 1
  9531. a926 1
  9532.     CloseUnlinkCleanup();
  9533. d1242 1
  9534. a1242 1
  9535. CloseUnlinkCleanup(VOID)
  9536. d1253 2
  9537. a1254 3
  9538.     /* We look for descriptors we switched into
  9539.      * non-blocking mode and reset them back
  9540.      * to blocking mode.
  9541. d1258 2
  9542. d1269 1
  9543. d2447 2
  9544. a5368 276
  9545. #define SEEK_ERROR (-1)
  9546.  
  9547. STATIC int
  9548. LockTheFile(int cmd,struct flock * l,struct UFB * ufb)
  9549. {
  9550.     int result = ERROR;
  9551.  
  9552.     /* Check for proper input. */
  9553.     if(l != NULL && ufb != NULL)
  9554.     {
  9555.         /* Can we make sense of the input parameters? */
  9556.         if(F_RDLCK <= l->l_type && l->l_type <= F_WRLCK &&
  9557.           (l->l_whence == SEEK_SET || l->l_whence == SEEK_CUR || l->l_whence == SEEK_END))
  9558.         {
  9559.             struct FileInfoBlock __aligned fib;
  9560.             BOOL dataIsValid = TRUE;
  9561.             LONG currentPosition;
  9562.             LONG start = 0;
  9563.             LONG len = 0;
  9564.  
  9565.             /* Now calculate the position of the
  9566.              * first byte to lock and the number
  9567.              * of bytes to lock.
  9568.              */
  9569.             switch(l->l_whence)
  9570.             {
  9571.                 case SEEK_SET:
  9572.  
  9573.                     start = l->l_start;
  9574.  
  9575.                     if(l->l_len == 0)
  9576.                     {
  9577.                         if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  9578.                             len = fib.fib_Size - start;
  9579.                         else
  9580.                             dataIsValid = FALSE;
  9581.                     }
  9582.                     else
  9583.                     {
  9584.                         len = l->l_len;
  9585.                     }
  9586.  
  9587.                     break;
  9588.  
  9589.                 case SEEK_CUR:
  9590.  
  9591.                     currentPosition = Seek((BPTR)ufb->ufbfh,0,OFFSET_CURRENT);
  9592.                     if(currentPosition != SEEK_ERROR)
  9593.                     {
  9594.                         start = currentPosition + l->l_start;
  9595.  
  9596.                         if(l->l_len == 0)
  9597.                         {
  9598.                             if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  9599.                                 len = fib.fib_Size - start;
  9600.                             else
  9601.                                 dataIsValid = FALSE;
  9602.                         }
  9603.                         else
  9604.                         {
  9605.                             len = l->l_len;
  9606.                         }
  9607.                     }
  9608.                     else
  9609.                     {
  9610.                         dataIsValid = FALSE;
  9611.                     }
  9612.  
  9613.                     break;
  9614.  
  9615.                 case SEEK_END:
  9616.                 default:
  9617.  
  9618.                     if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  9619.                     {
  9620.                         start = fib.fib_Size + l->l_start;
  9621.  
  9622.                         if(l->l_len == 0)
  9623.                             len = fib.fib_Size - start;
  9624.                         else
  9625.                             len = l->l_len;
  9626.                     }
  9627.                     else
  9628.                     {
  9629.                         dataIsValid = FALSE;
  9630.                     }
  9631.  
  9632.                     break;
  9633.             }
  9634.  
  9635.             SHOWVALUE(start);
  9636.             SHOWVALUE(len);
  9637.  
  9638.             /* Did we get everything we needed? */
  9639.             if(dataIsValid)
  9640.             {
  9641.                 if(start >= 0 && len >= 0)
  9642.                 {
  9643.                     if(len > 0)
  9644.                     {
  9645.                         if(l->l_type == F_UNLCK)
  9646.                         {
  9647.                             D(("unlocking %ld..%ld",start,start+len-1));
  9648.  
  9649.                             if(UnLockRecord((BPTR)ufb->ufbfh,start,len))
  9650.                                 result = OK;
  9651.                             else
  9652.                                 MapIoErrToErrno();
  9653.                         }
  9654.                         else
  9655.                         {
  9656.                             D(("  locking %ld..%ld",start,start+len-1));
  9657.  
  9658.                             if(cmd == F_SETLKW)
  9659.                             {
  9660.                                 LONG mode = (l->l_type == F_WRLCK) ? REC_EXCLUSIVE : REC_SHARED;
  9661.  
  9662.                                 if(mode == REC_EXCLUSIVE)
  9663.                                     D(("this is an exclusive lock; waiting for completion"));
  9664.                                 else
  9665.                                     D(("this is a shared lock; waiting for completion"));
  9666.  
  9667.                                 /* Retry until we manage to lock the record. */
  9668.                                 while(CANNOT LockRecord((BPTR)ufb->ufbfh,start,len,mode,TICKS_PER_SECOND / 2))
  9669.                                     chkabort();
  9670.  
  9671.                                 result = OK;
  9672.                             }
  9673.                             else
  9674.                             {
  9675.                                 LONG mode = (l->l_type == F_WRLCK) ? REC_EXCLUSIVE_IMMED : REC_SHARED_IMMED;
  9676.  
  9677.                                 if(mode == REC_EXCLUSIVE_IMMED)
  9678.                                     D(("this is an exclusive lock"));
  9679.                                 else
  9680.                                     D(("this is a shared lock"));
  9681.  
  9682.                                 if(LockRecord((BPTR)ufb->ufbfh,start,len,mode,0))
  9683.                                     result = OK;
  9684.                                 else
  9685.                                     MapIoErrToErrno();
  9686.                             }
  9687.                         }
  9688.                     }
  9689.                     else
  9690.                     {
  9691.                         SHOWMSG("zero length lock/unlock");
  9692.                         result = OK;
  9693.                     }
  9694.                 }
  9695.                 else
  9696.                 {
  9697.                     SHOWMSG("invalid start/len");
  9698.                     SHOWVALUE(start);
  9699.                     SHOWVALUE(len);
  9700.                     errno = EINVAL;
  9701.                 }
  9702.             }
  9703.             else
  9704.             {
  9705.                 SHOWMSG("couldn't determine start/len");
  9706.                 MapIoErrToErrno();
  9707.             }
  9708.         }
  9709.         else
  9710.         {
  9711.             SHOWMSG("invalid lock type or seek offset");
  9712.             SHOWVALUE(l->l_type);
  9713.             SHOWVALUE(l->l_whence);
  9714.             errno = EINVAL;
  9715.         }
  9716.     }
  9717.     else
  9718.     {
  9719.         SHOWMSG("no flock or no ufb");
  9720.         SHOWVALUE(l);
  9721.         SHOWVALUE(ufb);
  9722.  
  9723.         errno = EINVAL;
  9724.     }
  9725.  
  9726.     return(result);
  9727. }
  9728.  
  9729. int
  9730. amiga_fcntl(int fd,int cmd,unsigned long arg)
  9731. {
  9732.     struct UFB * ufb;
  9733.     struct flock * l;
  9734.     int result = ERROR;
  9735.  
  9736.     chkabort();
  9737.  
  9738.     ENTER();
  9739.  
  9740.     /* Don't try to lock data in a socket... */
  9741.     ufb = chkufb(fd);
  9742.     if(ufb == NULL || FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  9743.         ufb = NULL;
  9744.  
  9745.     l = (struct flock *)arg;
  9746.  
  9747.     switch(cmd)
  9748.     {
  9749.         /* Get the first lock that blocks the lock description pointed to
  9750.          * by the third argument, arg, taken as a pointer to a struct
  9751.          * flock (see above).  The information retrieved overwrites the
  9752.          * information passed to fcntl in the flock structure.  If no
  9753.          * lock is found that would prevent this lock from being created,
  9754.          * the structure is left unchanged by this function call except
  9755.          * for the lock type which is set to F_UNLCK.
  9756.          */
  9757.         case F_GETLK:
  9758.  
  9759.             SHOWMSG("F_GETLK");
  9760.             errno = ENOSYS;
  9761.             break;
  9762.  
  9763.         /* Set or clear a file segment lock according to the lock de-
  9764.          * scription pointed to by the third argument, arg, taken as a
  9765.          * pointer to a struct flock (see above).    F_SETLK is used to es-
  9766.          * tablish shared (or read) locks (F_RDLCK) or exclusive (or
  9767.          * write) locks, (F_WRLCK), as well as remove either type of lock
  9768.          * (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl
  9769.          * returns immediately with EACCES.
  9770.          */
  9771.         case F_SETLK:
  9772.  
  9773.             result = LockTheFile(cmd,l,ufb);
  9774.             break;
  9775.  
  9776.         /* This command is the same as F_SETLK except that if a shared or
  9777.          * exclusive lock is blocked by other locks, the process waits
  9778.          * until the request can be satisfied.  If a signal that is to be
  9779.          * caught is received while fcntl is waiting for a region, the
  9780.          * fcntl will be interrupted if the signal handler has not speci-
  9781.          * fied the SA_RESTART (see sigaction(2)).
  9782.          */
  9783.         case F_SETLKW:
  9784.  
  9785.             result = LockTheFile(cmd,l,ufb);
  9786.             break;
  9787.  
  9788.         /* Get descriptor status flags, as described below (arg is ig-
  9789.          * noted).
  9790.          */
  9791.         case F_GETFL:
  9792.  
  9793.             result = IsDescriptorNonblocking(fd) ? O_NONBLOCK : 0;
  9794.             break;
  9795.  
  9796.         /* Set descriptor status flags to arg. */
  9797.         case F_SETFL:
  9798.  
  9799.             if(FLAG_IS_SET(arg,O_NONBLOCK))
  9800.                 BlockDescriptor(fd);
  9801.             else
  9802.                 UnblockDescriptor(fd);
  9803.  
  9804.             result = OK;
  9805.             break;
  9806.  
  9807.         default:
  9808.  
  9809.             D(("Unknown command %ld",cmd));
  9810.             result = ERROR;
  9811.             errno = ENOSYS;
  9812.             break;
  9813.     }
  9814.  
  9815.     RETURN(result);
  9816.     return(result);
  9817. }
  9818.  
  9819. /******************************************************************************/
  9820.  
  9821. d5863 1
  9822. d5912 5
  9823. d6010 853
  9824. @
  9825.  
  9826.  
  9827. 1.3
  9828. log
  9829. @.
  9830. @
  9831. text
  9832. @d2 1
  9833. a2 1
  9834.  * $Id: amiga.c 1.2 1999/02/20 16:52:05 olsen Exp olsen $
  9835. d222 2
  9836. d6599 53
  9837. @
  9838.  
  9839.  
  9840. 1.2
  9841. log
  9842. @.
  9843. @
  9844. text
  9845. @d2 1
  9846. a2 1
  9847.  * $Id: amiga.c 1.1 1999/02/13 15:32:16 olsen Exp olsen $
  9848. d4476 70
  9849. d4676 1
  9850. a4676 1
  9851.                 struct MangleInfo mi;
  9852. d4678 2
  9853. a4679 1
  9854.                 if(MangleName(&whichPattern,&mi) == OK)
  9855. d4681 1
  9856. a4681 1
  9857.                     BPTR dirLock;
  9858. d4683 1
  9859. a4683 2
  9860.                     dirLock = Lock("",SHARED_LOCK);
  9861.                     if(dirLock != ZERO)
  9862. d4685 1
  9863. a4685 1
  9864.                         struct AnchorPath * ap;
  9865. d4687 1
  9866. a4687 2
  9867.                         ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9868.                         if(ap != NULL)
  9869. d4689 1
  9870. a4689 8
  9871.                             BOOL stopped = FALSE;
  9872.                             LONG error;
  9873.  
  9874.                             memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9875.                             ap->ap_Strlen        = MAX_FILENAME_LEN;
  9876.                             ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9877.  
  9878.                             if((error = MatchFirst(whichPattern,ap)) == OK)
  9879. d4691 1
  9880. a4691 13
  9881.                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  9882.  
  9883.                                 if(FIB_IS_DRAWER(&ap->ap_Info))
  9884.                                 {
  9885.                                     SHOWMSG("this is a drawer");
  9886.                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  9887.                                 }
  9888.                                 else
  9889.                                 {
  9890.                                     SHOWMSG("this is not a drawer");
  9891.                                 }
  9892.  
  9893.                                 do
  9894. d4693 1
  9895. a4693 10
  9896.                                     if(FIB_IS_FILE(&ap->ap_Info))
  9897.                                     {
  9898.                                         D(("Output |%s|",ap->ap_Buf));
  9899.                                         if(fprintf(out,"%s\n",ap->ap_Buf) < 0)
  9900.                                         {
  9901.                                             stopped = TRUE;
  9902.                                             break;
  9903.                                         }
  9904.                                     }
  9905.                                     else
  9906. d4695 2
  9907. a4696 1
  9908.                                         CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  9909. a4698 1
  9910.                                 while((error = MatchNext(ap)) == OK);
  9911. d4700 1
  9912. d4702 3
  9913. a4704 1
  9914.                             MatchEnd(ap);
  9915. d4706 1
  9916. a4706 1
  9917.                             if(NOT stopped)
  9918. d4708 6
  9919. a4713 15
  9920.                                 if(error == ERROR_NO_MORE_ENTRIES)
  9921.                                 {
  9922.                                     result = OK;
  9923.                                 }
  9924.                                 else if(error == ERROR_BREAK)
  9925.                                 {
  9926.                                     /* Don't do anything; we are going
  9927.                                      * to delete the file anyway.
  9928.                                      */
  9929.                                 }
  9930.                                 else
  9931.                                 {
  9932.                                     SetIoErr(error);
  9933.                                     MapIoErrToErrno();
  9934.                                 }
  9935. a4714 6
  9936.  
  9937.                             free(ap);
  9938.                         }
  9939.                         else
  9940.                         {
  9941.                             errno = ENOMEM;
  9942. a4715 2
  9943.  
  9944.                         UnLock(dirLock);
  9945. d4722 5
  9946. a4726 1
  9947.                     UnmangleName(&whichPattern,&mi);
  9948. d4831 1
  9949. a4831 2
  9950.                 char compiledPattern[2 * (MAX_FILENAME_LEN+1)];
  9951.                 LONG isWild;
  9952. d4833 1
  9953. a4833 3
  9954.                 isWild = ParsePatternNoCase(whichPattern,compiledPattern,sizeof(compiledPattern));
  9955.                 SHOWVALUE(isWild);
  9956.                 if(isWild != -1)
  9957. d4835 1
  9958. a4835 1
  9959.                     struct MangleInfo mi;
  9960. d4837 2
  9961. a4838 1
  9962.                     if(MangleName(&whichDrawer,&mi) == OK)
  9963. d4840 1
  9964. a4840 1
  9965.                         BPTR dirLock;
  9966. d4842 1
  9967. a4842 2
  9968.                         dirLock = Lock(whichDrawer,SHARED_LOCK);
  9969.                         if(dirLock != ZERO)
  9970. d4844 1
  9971. a4844 1
  9972.                             struct FileInfoBlock __aligned fib;
  9973. d4846 2
  9974. a4847 1
  9975.                             if(Examine(dirLock,&fib))
  9976. d4849 2
  9977. a4850 1
  9978.                                 struct AnchorPath * ap;
  9979. d4852 5
  9980. a4856 2
  9981.                                 ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9982.                                 if(ap != NULL)
  9983. d4858 3
  9984. a4860 2
  9985.                                     BOOL stopped = FALSE;
  9986.                                     LONG error;
  9987. d4862 1
  9988. a4862 7
  9989.                                     memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9990.                                     ap->ap_Strlen        = MAX_FILENAME_LEN;
  9991.                                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9992.  
  9993.                                     if((error = MatchFirst("",ap)) == OK)
  9994.                                     {
  9995.                                         do
  9996. d4864 2
  9997. a4865 1
  9998.                                             D(("checking |%s|",ap->ap_Buf));
  9999. d4867 1
  10000. a4867 1
  10001.                                             if(FIB_IS_FILE(&ap->ap_Info))
  10002. d4869 2
  10003. a4870 4
  10004.                                                 SHOWMSG("this is a file");
  10005.                                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  10006.  
  10007.                                                 if(MatchPatternNoCase(compiledPattern,ap->ap_Info.fib_FileName))
  10008. d4872 2
  10009. a4873 10
  10010.                                                     D(("Output |%s/%s|",whichDrawerBuffer,ap->ap_Buf));
  10011.                                                     if(fprintf(out,"%s/%s\n",whichDrawerBuffer,ap->ap_Buf) < 0)
  10012.                                                     {
  10013.                                                         stopped = TRUE;
  10014.                                                         break;
  10015.                                                     }
  10016.                                                 }
  10017.                                                 else
  10018.                                                 {
  10019.                                                     SHOWMSG("but its name does not match");
  10020. d4878 1
  10021. a4878 6
  10022.                                                 SHOWMSG("this is a drawer");
  10023.  
  10024.                                                 if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  10025.                                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  10026.                                                 else
  10027.                                                     CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  10028. a4880 17
  10029.                                         while((error = MatchNext(ap)) == OK);
  10030.                                     }
  10031.  
  10032.                                     MatchEnd(ap);
  10033.  
  10034.                                     if(NOT stopped)
  10035.                                     {
  10036.                                         if(error == ERROR_NO_MORE_ENTRIES)
  10037.                                         {
  10038.                                             result = OK;
  10039.                                         }
  10040.                                         else if(error == ERROR_BREAK)
  10041.                                         {
  10042.                                             /* Don't do anything; we are going
  10043.                                              * to delete the file anyway.
  10044.                                              */
  10045.                                         }
  10046. d4883 6
  10047. a4888 2
  10048.                                             SetIoErr(error);
  10049.                                             MapIoErrToErrno();
  10050. d4891 4
  10051. d4896 1
  10052. a4896 3
  10053.                                     free(ap);
  10054.                                 }
  10055.                                 else
  10056. d4898 15
  10057. a4912 1
  10058.                                     errno = ENOMEM;
  10059. d4914 2
  10060. d4919 1
  10061. a4919 1
  10062.                                 MapIoErrToErrno();
  10063. a4920 2
  10064.  
  10065.                             UnLock(dirLock);
  10066. d4927 1
  10067. a4927 1
  10068.                         UnmangleName(&whichDrawer,&mi);
  10069. d4929 6
  10070. a4934 4
  10071.                 }
  10072.                 else
  10073.                 {
  10074.                     MapIoErrToErrno();
  10075. @
  10076.  
  10077.  
  10078. 1.1
  10079. log
  10080. @.
  10081. @
  10082. text
  10083. @d221 1
  10084. d1006 9
  10085. a1014 2
  10086.                 /* Convert any "/dev/" reference to "NIL:". */
  10087.                 name = "NIL:";
  10088. d1303 2
  10089. d1489 1
  10090. a1489 1
  10091.     BOOL isAbsolutePath = FALSE;
  10092. d4476 14
  10093. d4493 2
  10094. d4497 5
  10095. d4505 2
  10096. d4512 420
  10097. a4931 1
  10098.     if(MangleName(&cmd,&mi) == OK)
  10099. d4933 5
  10100. a4937 3
  10101.         ForbidDOS();
  10102.         result = system(cmd);
  10103.         PermitDOS();
  10104. d4939 2
  10105. a4940 1
  10106.         UnmangleName(&cmd,&mi);
  10107. d4944 1
  10108. d6244 1
  10109. a6244 1
  10110.     int result;
  10111. d6256 1
  10112. a6256 2
  10113.         result = recv(ufb->ufbfh,&c,1,0);
  10114.         if(result == 1)
  10115. a6257 2
  10116.  
  10117.         RETURN(result);
  10118. d6264 1
  10119. d6272 1
  10120. a6272 1
  10121.     char *result = NULL;
  10122. d6381 1
  10123. d6553 22
  10124. @
  10125.